sbox-mcp-server 1.19.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +119 -82
- package/dist/tools/assets.js +5 -5
- package/dist/tools/audio.js +12 -19
- package/dist/tools/audit.d.ts +8 -0
- package/dist/tools/audit.js +65 -0
- package/dist/tools/batch.d.ts +8 -0
- package/dist/tools/batch.js +77 -0
- package/dist/tools/characters.js +6 -6
- package/dist/tools/cinematics.d.ts +19 -0
- package/dist/tools/cinematics.js +73 -0
- package/dist/tools/components.js +2 -2
- package/dist/tools/debugdraw.js +4 -4
- package/dist/tools/diagnostics.js +7 -5
- package/dist/tools/discovery.js +6 -6
- package/dist/tools/gameobjects.js +7 -7
- package/dist/tools/gameplay.js +4 -4
- package/dist/tools/inspection.js +6 -6
- package/dist/tools/interactionpack.d.ts +16 -0
- package/dist/tools/interactionpack.js +107 -0
- package/dist/tools/leveltools.js +5 -5
- package/dist/tools/looteconomy.d.ts +18 -0
- package/dist/tools/looteconomy.js +107 -0
- package/dist/tools/materials.js +4 -4
- package/dist/tools/moviemaker.d.ts +17 -0
- package/dist/tools/moviemaker.js +98 -0
- package/dist/tools/netprimitives.d.ts +18 -0
- package/dist/tools/netprimitives.js +110 -0
- package/dist/tools/networking.js +22 -22
- package/dist/tools/physics.js +4 -4
- package/dist/tools/playmode.js +5 -5
- package/dist/tools/playtest.js +2 -1
- package/dist/tools/prefabs.js +7 -3
- package/dist/tools/project.js +2 -2
- package/dist/tools/publishing.js +3 -3
- package/dist/tools/scenes.js +2 -2
- package/dist/tools/scripts.js +3 -3
- package/dist/tools/status.js +1 -1
- package/dist/tools/templates.js +7 -7
- package/dist/tools/ui.js +5 -5
- package/dist/tools/uifeedback.d.ts +16 -0
- package/dist/tools/uifeedback.js +83 -0
- package/dist/tools/vehicles.d.ts +8 -0
- package/dist/tools/vehicles.js +98 -0
- package/dist/tools/visuals.js +8 -8
- package/dist/tools/workflow.d.ts +8 -0
- package/dist/tools/workflow.js +107 -0
- package/dist/tools/world.js +61 -58
- package/package.json +55 -55
package/dist/index.js
CHANGED
|
@@ -53,6 +53,16 @@ import { registerStationTools } from "./tools/stations.js";
|
|
|
53
53
|
import { registerDirectorTools } from "./tools/director.js";
|
|
54
54
|
import { registerSaveSlotsTools } from "./tools/saveslots.js";
|
|
55
55
|
import { registerGameFeelTools } from "./tools/gamefeel.js";
|
|
56
|
+
import { registerMovieMakerTools } from "./tools/moviemaker.js";
|
|
57
|
+
import { registerNetPrimitivesTools } from "./tools/netprimitives.js";
|
|
58
|
+
import { registerInteractionPackTools } from "./tools/interactionpack.js";
|
|
59
|
+
import { registerLootEconomyTools } from "./tools/looteconomy.js";
|
|
60
|
+
import { registerUiFeedbackTools } from "./tools/uifeedback.js";
|
|
61
|
+
import { registerCinematicsTools } from "./tools/cinematics.js";
|
|
62
|
+
import { registerAuditTools } from "./tools/audit.js";
|
|
63
|
+
import { registerBatchTools } from "./tools/batch.js";
|
|
64
|
+
import { registerWorkflowTools } from "./tools/workflow.js";
|
|
65
|
+
import { registerVehicleTools } from "./tools/vehicles.js";
|
|
56
66
|
// ── CLI flags ──────────────────────────────────────────────────────
|
|
57
67
|
const args = process.argv.slice(2);
|
|
58
68
|
/** Read the package version from package.json, or return "unknown" on failure. */
|
|
@@ -72,68 +82,68 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
72
82
|
process.exit(0);
|
|
73
83
|
}
|
|
74
84
|
if (args.includes("--help") || args.includes("-h")) {
|
|
75
|
-
console.log(`sbox-mcp ${getVersion()} — MCP Server for s&box game engine
|
|
76
|
-
|
|
77
|
-
USAGE
|
|
78
|
-
node dist/index.js Start the MCP server (stdio transport)
|
|
79
|
-
node dist/index.js --help Show this help
|
|
80
|
-
node dist/index.js --version Show version
|
|
81
|
-
|
|
82
|
-
ENVIRONMENT VARIABLES
|
|
83
|
-
SBOX_BRIDGE_IPC_DIR IPC directory — MUST match the s&box addon's dir.
|
|
84
|
-
Default: <os tmpdir>/sbox-bridge-ipc
|
|
85
|
-
SBOX_BRIDGE_HOST Legacy/cosmetic — shown in get_bridge_status only
|
|
86
|
-
SBOX_BRIDGE_PORT Legacy/cosmetic — shown in get_bridge_status only
|
|
87
|
-
|
|
88
|
-
CONNECT TO CLAUDE CODE
|
|
89
|
-
claude mcp add sbox -- node /path/to/sbox-mcp-server/dist/index.js
|
|
90
|
-
|
|
91
|
-
TOOLS (
|
|
92
|
-
Project: get_project_info, list_project_files, read_file, write_file
|
|
93
|
-
Scripts: create_script, edit_script, delete_script, trigger_hotload
|
|
94
|
-
Scenes: list_scenes, load_scene, save_scene, create_scene
|
|
95
|
-
GameObjects: create/delete/duplicate/rename_gameobject, set_parent/enabled/transform
|
|
96
|
-
Components: get/set_property, get_all_properties, list_available_components, add_component_with_properties, set_prefab_ref
|
|
97
|
-
Hierarchy: get_scene_hierarchy (with maxDepth + rootId), get_selected_objects, select_object, focus_object
|
|
98
|
-
Assets: search_assets, list_asset_library, install_asset, get_asset_info
|
|
99
|
-
Materials: assign_model, create_material, assign_material, set_material_property
|
|
100
|
-
Audio: list_sounds, create_sound_event, assign_sound, play_sound_preview
|
|
101
|
-
Play Mode: start_play, stop_play, is_playing
|
|
102
|
-
Runtime: get/set_runtime_property, take_screenshot
|
|
103
|
-
Editor: undo, redo
|
|
104
|
-
Prefabs: create_prefab, instantiate_prefab, list_prefabs, get_prefab_info
|
|
105
|
-
Physics: add_physics, add_collider, add_joint, raycast
|
|
106
|
-
UI: create_razor_ui, add_screen_panel, add_world_panel
|
|
107
|
-
Templates: create_player_controller, create_npc_controller, create_game_manager, create_trigger_zone
|
|
108
|
-
Networking: add_network_helper, configure_network, get_network_status, network_spawn, set_ownership
|
|
109
|
-
Net Scripts: add_sync_property, add_rpc_method, create_networked_player, create_lobby_manager, create_network_events
|
|
110
|
-
Publishing: get_project_config, set_project_config, validate_project, set_project_thumbnail, get_package_details
|
|
111
|
-
World Gen: invoke_button, list_component_buttons, raycast_terrain, build_terrain_mesh
|
|
112
|
-
Map Edit: add_terrain_hill/clearing/trail, clear_terrain_features, sculpt_terrain
|
|
113
|
-
Caves: add_cave_waypoint, clear_cave_path
|
|
114
|
-
Forest: add_forest_poi/trail, set_forest_seed, clear_forest_pois, paint_forest_density
|
|
115
|
-
Placement: place_along_path
|
|
116
|
-
Discovery: describe_type, search_types, get_method_signature, find_in_project
|
|
117
|
-
Status: get_bridge_status
|
|
118
|
-
|
|
119
|
-
── New in v1.4.0 ───────────────────────────────────
|
|
120
|
-
Visual: add_light, set_fog, add_post_process, set_skybox, add_envmap_probe, apply_atmosphere, apply_post_fx_look
|
|
121
|
-
Characters: spawn_model, spawn_citizen, dress_citizen, set_bodygroup, pose_citizen, equip_model, set_look_at, add_ragdoll, set_expression
|
|
122
|
-
Scene: snap_to_ground, align_objects, distribute_objects, grid_duplicate, measure_distance
|
|
123
|
-
Environment: scatter_props, randomize_transforms, group_objects
|
|
124
|
-
Utilities: find_objects, set_tint, replace_model, set_tags
|
|
125
|
-
VFX (exp): spawn_particle, create_particle_effect, add_trail, add_beam
|
|
126
|
-
|
|
127
|
-
── New in v1.5.0 ───────────────────────────────────
|
|
128
|
-
Diagnostics: read_log, get_compile_errors (MCP-server-side — work even if the editor crashed)
|
|
129
|
-
Camera: screenshot_from (AIM a shot at an object/point — take_screenshot is fixed to the Main Camera), frame_camera
|
|
130
|
-
Navigation: bake_navmesh, get_navmesh_path
|
|
131
|
-
Spatial: physics_overlap (volume counterpart to raycast)
|
|
132
|
-
Reflections: bake_reflections
|
|
133
|
-
Particles: spawn_vpcf (compiled .vpcf via LegacyParticleSystem — the supported particle path)
|
|
134
|
-
Console/Exec: console_run, execute_csharp (experimental)
|
|
135
|
-
Object utils: remove_component, get_tags
|
|
136
|
-
Docs search: search_docs, get_doc_page, list_doc_categories (MCP-server-side — official Facepunch/sbox-docs)
|
|
85
|
+
console.log(`sbox-mcp ${getVersion()} — MCP Server for s&box game engine
|
|
86
|
+
|
|
87
|
+
USAGE
|
|
88
|
+
node dist/index.js Start the MCP server (stdio transport)
|
|
89
|
+
node dist/index.js --help Show this help
|
|
90
|
+
node dist/index.js --version Show version
|
|
91
|
+
|
|
92
|
+
ENVIRONMENT VARIABLES
|
|
93
|
+
SBOX_BRIDGE_IPC_DIR IPC directory — MUST match the s&box addon's dir.
|
|
94
|
+
Default: <os tmpdir>/sbox-bridge-ipc
|
|
95
|
+
SBOX_BRIDGE_HOST Legacy/cosmetic — shown in get_bridge_status only
|
|
96
|
+
SBOX_BRIDGE_PORT Legacy/cosmetic — shown in get_bridge_status only
|
|
97
|
+
|
|
98
|
+
CONNECT TO CLAUDE CODE
|
|
99
|
+
claude mcp add sbox -- node /path/to/sbox-mcp-server/dist/index.js
|
|
100
|
+
|
|
101
|
+
TOOLS (245 total / 237 editor handlers · v2: the native editor MCP server at http://127.0.0.1:7269/mcp is the primary path — this stdio server is the full-surface fallback; --lifeline exposes just the editor-down diagnostics)
|
|
102
|
+
Project: get_project_info, list_project_files, read_file, write_file
|
|
103
|
+
Scripts: create_script, edit_script, delete_script, trigger_hotload
|
|
104
|
+
Scenes: list_scenes, load_scene, save_scene, create_scene
|
|
105
|
+
GameObjects: create/delete/duplicate/rename_gameobject, set_parent/enabled/transform
|
|
106
|
+
Components: get/set_property, get_all_properties, list_available_components, add_component_with_properties, set_prefab_ref
|
|
107
|
+
Hierarchy: get_scene_hierarchy (with maxDepth + rootId), get_selected_objects, select_object, focus_object
|
|
108
|
+
Assets: search_assets, list_asset_library, install_asset, get_asset_info
|
|
109
|
+
Materials: assign_model, create_material, assign_material, set_material_property
|
|
110
|
+
Audio: list_sounds, create_sound_event, assign_sound, play_sound_preview
|
|
111
|
+
Play Mode: start_play, stop_play, is_playing
|
|
112
|
+
Runtime: get/set_runtime_property, take_screenshot
|
|
113
|
+
Editor: undo, redo
|
|
114
|
+
Prefabs: create_prefab, instantiate_prefab, list_prefabs, get_prefab_info
|
|
115
|
+
Physics: add_physics, add_collider, add_joint, raycast
|
|
116
|
+
UI: create_razor_ui, add_screen_panel, add_world_panel
|
|
117
|
+
Templates: create_player_controller, create_npc_controller, create_game_manager, create_trigger_zone
|
|
118
|
+
Networking: add_network_helper, configure_network, get_network_status, network_spawn, set_ownership
|
|
119
|
+
Net Scripts: add_sync_property, add_rpc_method, create_networked_player, create_lobby_manager, create_network_events
|
|
120
|
+
Publishing: get_project_config, set_project_config, validate_project, set_project_thumbnail, get_package_details
|
|
121
|
+
World Gen: invoke_button, list_component_buttons, raycast_terrain, build_terrain_mesh
|
|
122
|
+
Map Edit: add_terrain_hill/clearing/trail, clear_terrain_features, sculpt_terrain
|
|
123
|
+
Caves: add_cave_waypoint, clear_cave_path
|
|
124
|
+
Forest: add_forest_poi/trail, set_forest_seed, clear_forest_pois, paint_forest_density
|
|
125
|
+
Placement: place_along_path
|
|
126
|
+
Discovery: describe_type, search_types, get_method_signature, find_in_project
|
|
127
|
+
Status: get_bridge_status
|
|
128
|
+
|
|
129
|
+
── New in v1.4.0 ───────────────────────────────────
|
|
130
|
+
Visual: add_light, set_fog, add_post_process, set_skybox, add_envmap_probe, apply_atmosphere, apply_post_fx_look
|
|
131
|
+
Characters: spawn_model, spawn_citizen, dress_citizen, set_bodygroup, pose_citizen, equip_model, set_look_at, add_ragdoll, set_expression
|
|
132
|
+
Scene: snap_to_ground, align_objects, distribute_objects, grid_duplicate, measure_distance
|
|
133
|
+
Environment: scatter_props, randomize_transforms, group_objects
|
|
134
|
+
Utilities: find_objects, set_tint, replace_model, set_tags
|
|
135
|
+
VFX (exp): spawn_particle, create_particle_effect, add_trail, add_beam
|
|
136
|
+
|
|
137
|
+
── New in v1.5.0 ───────────────────────────────────
|
|
138
|
+
Diagnostics: read_log, get_compile_errors (MCP-server-side — work even if the editor crashed)
|
|
139
|
+
Camera: screenshot_from (AIM a shot at an object/point — take_screenshot is fixed to the Main Camera), frame_camera
|
|
140
|
+
Navigation: bake_navmesh, get_navmesh_path
|
|
141
|
+
Spatial: physics_overlap (volume counterpart to raycast)
|
|
142
|
+
Reflections: bake_reflections
|
|
143
|
+
Particles: spawn_vpcf (compiled .vpcf via LegacyParticleSystem — the supported particle path)
|
|
144
|
+
Console/Exec: console_run, execute_csharp (experimental)
|
|
145
|
+
Object utils: remove_component, get_tags
|
|
146
|
+
Docs search: search_docs, get_doc_page, list_doc_categories (MCP-server-side — official Facepunch/sbox-docs)
|
|
137
147
|
`);
|
|
138
148
|
process.exit(0);
|
|
139
149
|
}
|
|
@@ -146,30 +156,47 @@ const server = new McpServer({
|
|
|
146
156
|
// server (the way other MCP servers like Supabase / TurboTax do). Use it to
|
|
147
157
|
// tell Claude how to work effectively with the bridge — the disciplines that
|
|
148
158
|
// are easy to skip without a reminder.
|
|
149
|
-
instructions: `You are working with the s&box Claude Bridge — a file-based IPC bridge into the s&box game engine editor.
|
|
150
|
-
|
|
151
|
-
To get good results:
|
|
152
|
-
|
|
153
|
-
1. Always call \`mcp__sbox__get_bridge_status\` first to confirm the bridge addon is connected and s&box is running. If ping responds but other tools time out, the editor side isn't processing requests.
|
|
154
|
-
|
|
155
|
-
2. For visual changes (models, positions, animations, UI panels, lighting), call \`mcp__sbox__take_screenshot\` after the change and READ THE PNG yourself. You're a multimodal model — you can see the result. Guessing about visual outcomes from code alone produces long iteration loops. The screenshot tool saves to <sbox-install>/screenshots/sbox.<timestamp>.png — list the newest file and read it.
|
|
156
|
-
|
|
157
|
-
3. Before writing code that touches an unfamiliar s&box type, call \`mcp__sbox__describe_type\` or \`mcp__sbox__search_types\`. s&box's API changes between SDK versions — reflection is the source of truth, not training data.
|
|
158
|
-
|
|
159
|
-
4. \`get_scene_hierarchy\` honors \`maxDepth\` (default 10) and accepts optional \`rootId\` to traverse from a specific GameObject. Use these to avoid dumping the entire scene into a tool result.
|
|
160
|
-
|
|
161
|
-
5. Scene-mutating tools (create_gameobject, set_property, etc.) refuse during play mode and return a clear error. Stop play before making scene edits.
|
|
162
|
-
|
|
163
|
-
6. First session with the bridge (or when the user asks "how do I start?" / "what can this do?")? Offer to run setup — invoke the \`sbox-setup\` skill: it verifies the connection, detects the user's installed libraries (\`list_libraries\`), recommends a first move, and points to help + feedback.
|
|
164
|
-
|
|
165
|
-
If you're running inside Claude Code, install the companion plugin for the full workflow:
|
|
166
|
-
/plugin marketplace add LouSputthole/Sbox-Claude
|
|
167
|
-
/plugin install sbox-claude
|
|
168
|
-
|
|
159
|
+
instructions: `You are working with the s&box Claude Bridge — a file-based IPC bridge into the s&box game engine editor.
|
|
160
|
+
|
|
161
|
+
To get good results:
|
|
162
|
+
|
|
163
|
+
1. Always call \`mcp__sbox__get_bridge_status\` first to confirm the bridge addon is connected and s&box is running. If ping responds but other tools time out, the editor side isn't processing requests.
|
|
164
|
+
|
|
165
|
+
2. For visual changes (models, positions, animations, UI panels, lighting), call \`mcp__sbox__take_screenshot\` after the change and READ THE PNG yourself. You're a multimodal model — you can see the result. Guessing about visual outcomes from code alone produces long iteration loops. The screenshot tool saves to <sbox-install>/screenshots/sbox.<timestamp>.png — list the newest file and read it.
|
|
166
|
+
|
|
167
|
+
3. Before writing code that touches an unfamiliar s&box type, call \`mcp__sbox__describe_type\` or \`mcp__sbox__search_types\`. s&box's API changes between SDK versions — reflection is the source of truth, not training data.
|
|
168
|
+
|
|
169
|
+
4. \`get_scene_hierarchy\` honors \`maxDepth\` (default 10) and accepts optional \`rootId\` to traverse from a specific GameObject. Use these to avoid dumping the entire scene into a tool result.
|
|
170
|
+
|
|
171
|
+
5. Scene-mutating tools (create_gameobject, set_property, etc.) refuse during play mode and return a clear error. Stop play before making scene edits.
|
|
172
|
+
|
|
173
|
+
6. First session with the bridge (or when the user asks "how do I start?" / "what can this do?")? Offer to run setup — invoke the \`sbox-setup\` skill: it verifies the connection, detects the user's installed libraries (\`list_libraries\`), recommends a first move, and points to help + feedback.
|
|
174
|
+
|
|
175
|
+
If you're running inside Claude Code, install the companion plugin for the full workflow:
|
|
176
|
+
/plugin marketplace add LouSputthole/Sbox-Claude
|
|
177
|
+
/plugin install sbox-claude
|
|
178
|
+
|
|
169
179
|
The plugin ships an \`sbox-build-feature\` skill that codifies the workflow above plus a list of common s&box gotchas (MathF not available in sandbox, Cloud assets ephemeral, head bone case-sensitive, CitizenAnimationHelper.IkRightHand works at runtime, etc.). Read its SKILL.md before starting non-trivial features.`,
|
|
170
180
|
});
|
|
171
181
|
// Bridge client talks to the s&box editor via file IPC. host/port are cosmetic.
|
|
172
182
|
const bridge = new BridgeClient(process.env.SBOX_BRIDGE_HOST ?? "127.0.0.1", parseInt(process.env.SBOX_BRIDGE_PORT ?? "29015", 10));
|
|
183
|
+
// ── Lifeline mode (v2 migration) ───────────────────────────────────
|
|
184
|
+
// With the native editor MCP server carrying the full tool surface, this stdio
|
|
185
|
+
// server's long-term job is "editor-down diagnostics": the native server dies
|
|
186
|
+
// with the editor; these tools read the log / docs directly and don't. --lifeline
|
|
187
|
+
// registers ONLY that set by filtering server.tool() — everything else is a no-op.
|
|
188
|
+
const LIFELINE_TOOLS = new Set([
|
|
189
|
+
"read_log", "get_compile_errors", "search_docs", "get_doc_page",
|
|
190
|
+
"list_doc_categories", "run_self_test", "get_bridge_status",
|
|
191
|
+
]);
|
|
192
|
+
if (args.includes("--lifeline")) {
|
|
193
|
+
const realTool = server.tool.bind(server);
|
|
194
|
+
server.tool = (...toolArgs) => {
|
|
195
|
+
if (LIFELINE_TOOLS.has(toolArgs[0]))
|
|
196
|
+
return realTool(...toolArgs);
|
|
197
|
+
return undefined;
|
|
198
|
+
};
|
|
199
|
+
}
|
|
173
200
|
// Register all tools
|
|
174
201
|
registerProjectTools(server, bridge);
|
|
175
202
|
registerScriptTools(server, bridge);
|
|
@@ -209,6 +236,16 @@ registerStationTools(server, bridge);
|
|
|
209
236
|
registerDirectorTools(server, bridge);
|
|
210
237
|
registerSaveSlotsTools(server, bridge);
|
|
211
238
|
registerGameFeelTools(server, bridge);
|
|
239
|
+
registerMovieMakerTools(server, bridge);
|
|
240
|
+
registerNetPrimitivesTools(server, bridge);
|
|
241
|
+
registerInteractionPackTools(server, bridge);
|
|
242
|
+
registerLootEconomyTools(server, bridge);
|
|
243
|
+
registerUiFeedbackTools(server, bridge);
|
|
244
|
+
registerCinematicsTools(server, bridge);
|
|
245
|
+
registerAuditTools(server, bridge);
|
|
246
|
+
registerBatchTools(server, bridge);
|
|
247
|
+
registerWorkflowTools(server, bridge);
|
|
248
|
+
registerVehicleTools(server, bridge);
|
|
212
249
|
/** Start the MCP server on stdio and attempt initial Bridge connection. */
|
|
213
250
|
async function main() {
|
|
214
251
|
const transport = new StdioServerTransport();
|
package/dist/tools/assets.js
CHANGED
|
@@ -28,19 +28,19 @@ export function registerAssetTools(server, bridge) {
|
|
|
28
28
|
};
|
|
29
29
|
});
|
|
30
30
|
// ── list_asset_library ───────────────────────────────────────────
|
|
31
|
-
server.tool("list_asset_library", "
|
|
31
|
+
server.tool("list_asset_library", "List assets visible to the editor's AssetSystem — project assets plus mounted engine/installed-package content (it does NOT query the remote sbox.game library; use install_asset to pull in new packages). Returns { count, assets:[{ name, path, relativePath, assetType }] } — pass a returned path to spawn_model, assign_model, or get_asset_info", {
|
|
32
32
|
query: z
|
|
33
33
|
.string()
|
|
34
34
|
.optional()
|
|
35
|
-
.describe("Search term
|
|
35
|
+
.describe("Search term, case-insensitive substring match against asset NAMES"),
|
|
36
36
|
type: z
|
|
37
37
|
.string()
|
|
38
38
|
.optional()
|
|
39
|
-
.describe("
|
|
39
|
+
.describe("Asset type filter, substring-matched against the asset's type (e.g. 'model', 'material', 'sound')"),
|
|
40
40
|
maxResults: z
|
|
41
41
|
.number()
|
|
42
42
|
.optional()
|
|
43
|
-
.describe("Maximum results. Defaults to
|
|
43
|
+
.describe("Maximum results. Defaults to 200"),
|
|
44
44
|
}, async (params) => {
|
|
45
45
|
const res = await bridge.send("list_asset_library", params);
|
|
46
46
|
if (!res.success) {
|
|
@@ -51,7 +51,7 @@ export function registerAssetTools(server, bridge) {
|
|
|
51
51
|
};
|
|
52
52
|
});
|
|
53
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", {
|
|
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. Returns { installed, ident, name, path, relativePath, restartRecommended, note } — pass the returned path to spawn_model / assign_model. CAUTION: if the package is a code LIBRARY (adds a PackageReference), trigger_hotload will NOT surface its types — call restart_editor so the new package compiles into the project", {
|
|
55
55
|
ident: z
|
|
56
56
|
.string()
|
|
57
57
|
.describe("Package identifier (e.g. 'facepunch.flatgrass', 'author.package_name')"),
|
package/dist/tools/audio.js
CHANGED
|
@@ -5,15 +5,15 @@ import { z } from "zod";
|
|
|
5
5
|
*/
|
|
6
6
|
export function registerAudioTools(server, bridge) {
|
|
7
7
|
// ── list_sounds ──────────────────────────────────────────────────
|
|
8
|
-
server.tool("list_sounds", "List
|
|
8
|
+
server.tool("list_sounds", "List the project's .sound event files (recursive scan of the project root for *.sound). Returns { count, sounds } — project-relative paths ready to pass to assign_sound, play_sound_preview, or add_lipsync. NOTE: the current handler returns every match (filter/maxResults are not applied) and only covers .sound files in the project tree — use search_assets type='sound' for other sound assets", {
|
|
9
9
|
filter: z
|
|
10
10
|
.string()
|
|
11
11
|
.optional()
|
|
12
|
-
.describe("Search filter for sound name or path"),
|
|
12
|
+
.describe("Search filter for sound name or path (currently not applied by the handler — all .sound files are returned)"),
|
|
13
13
|
maxResults: z
|
|
14
14
|
.number()
|
|
15
15
|
.optional()
|
|
16
|
-
.describe("Maximum results. Defaults to 50"),
|
|
16
|
+
.describe("Maximum results. Defaults to 50 (currently not applied by the handler)"),
|
|
17
17
|
}, async (params) => {
|
|
18
18
|
const res = await bridge.send("list_sounds", params);
|
|
19
19
|
if (!res.success) {
|
|
@@ -24,13 +24,14 @@ export function registerAudioTools(server, bridge) {
|
|
|
24
24
|
};
|
|
25
25
|
});
|
|
26
26
|
// ── create_sound_event ───────────────────────────────────────────
|
|
27
|
-
server.tool("create_sound_event", "Create a
|
|
27
|
+
server.tool("create_sound_event", "Create a .sound event file wired to a source .vsnd. Returns { created, path, soundReferenced, note } (path is project-relative); errors if the file already exists. Preview the result with play_sound_preview or attach it to an object with assign_sound. Note: .sound events have no loop flag — looping lives on the SoundPointComponent that plays the event", {
|
|
28
28
|
path: z
|
|
29
29
|
.string()
|
|
30
|
-
.describe("
|
|
30
|
+
.describe("Project-relative path for the sound event file (e.g. 'sounds/footstep.sound'; '.sound' appended if missing)"),
|
|
31
31
|
sound: z
|
|
32
32
|
.string()
|
|
33
|
-
.
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("Path to the source sound asset (.vsnd) the event plays. Omit to create an empty event and wire it later"),
|
|
34
35
|
volume: z
|
|
35
36
|
.number()
|
|
36
37
|
.optional()
|
|
@@ -39,18 +40,10 @@ export function registerAudioTools(server, bridge) {
|
|
|
39
40
|
.number()
|
|
40
41
|
.optional()
|
|
41
42
|
.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
43
|
maxDistance: z
|
|
47
44
|
.number()
|
|
48
45
|
.optional()
|
|
49
|
-
.describe("Maximum audible distance (
|
|
50
|
-
loop: z
|
|
51
|
-
.boolean()
|
|
52
|
-
.optional()
|
|
53
|
-
.describe("Whether the sound should loop. Defaults to false"),
|
|
46
|
+
.describe("Maximum audible distance in units (sets Distance + enables DistanceAttenuation). Omit for the engine default"),
|
|
54
47
|
}, async (params) => {
|
|
55
48
|
const res = await bridge.send("create_sound_event", params);
|
|
56
49
|
if (!res.success) {
|
|
@@ -61,7 +54,7 @@ export function registerAudioTools(server, bridge) {
|
|
|
61
54
|
};
|
|
62
55
|
});
|
|
63
56
|
// ── assign_sound ─────────────────────────────────────────────────
|
|
64
|
-
server.tool("assign_sound", "Attach a sound event to a GameObject via SoundPointComponent. Creates the component if needed", {
|
|
57
|
+
server.tool("assign_sound", "Attach a sound event to a GameObject via SoundPointComponent. Creates the component if needed. Returns { assigned, id, sound, soundLoaded, playOnStart } — soundLoaded:false means the .sound path did not resolve (the component is still added with no event; verify the path with list_sounds)", {
|
|
65
58
|
id: z.string().describe("GUID of the GameObject"),
|
|
66
59
|
sound: z
|
|
67
60
|
.string()
|
|
@@ -69,7 +62,7 @@ export function registerAudioTools(server, bridge) {
|
|
|
69
62
|
playOnStart: z
|
|
70
63
|
.boolean()
|
|
71
64
|
.optional()
|
|
72
|
-
.describe("
|
|
65
|
+
.describe("If true, the handler calls StartSound() immediately, so the sound starts playing right away (audible in the editor)"),
|
|
73
66
|
}, async (params) => {
|
|
74
67
|
const res = await bridge.send("assign_sound", params);
|
|
75
68
|
if (!res.success) {
|
|
@@ -80,14 +73,14 @@ export function registerAudioTools(server, bridge) {
|
|
|
80
73
|
};
|
|
81
74
|
});
|
|
82
75
|
// ── play_sound_preview ───────────────────────────────────────────
|
|
83
|
-
server.tool("play_sound_preview", "Play a sound in the editor for testing without entering play mode", {
|
|
76
|
+
server.tool("play_sound_preview", "Play a sound in the editor for testing without entering play mode. Returns { playing, sound, volume }. Fire-and-forget via Sound.Play — there is no stop control, and the volume param is echoed back but not currently applied to playback", {
|
|
84
77
|
sound: z
|
|
85
78
|
.string()
|
|
86
79
|
.describe("Sound event or asset path to preview"),
|
|
87
80
|
volume: z
|
|
88
81
|
.number()
|
|
89
82
|
.optional()
|
|
90
|
-
.describe("Preview volume (0-1). Defaults to 1.0"),
|
|
83
|
+
.describe("Preview volume (0-1). Defaults to 1.0 (echoed in the response but not currently applied to playback)"),
|
|
91
84
|
}, async (params) => {
|
|
92
85
|
const res = await bridge.send("play_sound_preview", params);
|
|
93
86
|
if (!res.success) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { BridgeClient } from "../transport/bridge-client.js";
|
|
3
|
+
/**
|
|
4
|
+
* Project audit & batch operation tools (v2 relaunch wave 1, Batch 51):
|
|
5
|
+
* find_broken_references, batch_set_property, describe_project.
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerAuditTools(server: McpServer, bridge: BridgeClient): void;
|
|
8
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Project audit & batch operation tools (v2 relaunch wave 1, Batch 51):
|
|
4
|
+
* find_broken_references, batch_set_property, describe_project.
|
|
5
|
+
*/
|
|
6
|
+
export function registerAuditTools(server, bridge) {
|
|
7
|
+
// ── find_broken_references ───────────────────────────────────────
|
|
8
|
+
server.tool("find_broken_references", "Scan the project for broken references, two layers in one call: (1) every GameObject in the open scene — renderers with no Model (missing_model), component properties pointing at DESTROYED GameObjects/Components (dead_gameobject_ref / dead_component_ref), null component entries whose type no longer exists (missing_component); (2) every .scene/.prefab FILE — prefab references to deleted/renamed files (missing_prefab_file). Returns { total, showing, truncated, objectsScanned, filesScanned, issues } — each issue has { id, name, component, kind, detail } (file-level issues carry the file path in name). Fix missing models with assign_model, dead refs with set_property/set_component_reference, missing prefab files by fixing the path or recreating via create_prefab. Read-only; safe any time. Results cap at `limit` (default 100, max 500)", {
|
|
9
|
+
limit: z
|
|
10
|
+
.number()
|
|
11
|
+
.int()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("Max issues to return (default 100, max 500). total still counts everything"),
|
|
14
|
+
scanFiles: z
|
|
15
|
+
.boolean()
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Include the .scene/.prefab file scan for missing prefab references. Default true"),
|
|
18
|
+
}, async (params) => {
|
|
19
|
+
const res = await bridge.send("find_broken_references", params);
|
|
20
|
+
if (!res.success) {
|
|
21
|
+
return { content: [{ type: "text", text: `Error: ${res.error}` }] };
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
// ── batch_set_property ───────────────────────────────────────────
|
|
28
|
+
server.tool("batch_set_property", "Set ONE component property to the same value across MANY GameObjects in a single call (e.g. Tint on 40 props, Enabled on every light). Pass dryRun:true first to validate — it reports each object's current value and what would change WITHOUT applying anything. Returns { total, succeeded, failed, dryRun, results } with per-object ok/error and the previous value on success. Get ids from find_objects or get_selected_objects. Scene-mutating: refused during play mode. Value coercion matches set_property (numbers, bools, enums, 'x,y,z' vectors, colors, asset paths)", {
|
|
29
|
+
ids: z
|
|
30
|
+
.array(z.string())
|
|
31
|
+
.describe("GUIDs of the GameObjects to modify (from find_objects, get_scene_hierarchy, or get_selected_objects)"),
|
|
32
|
+
component: z
|
|
33
|
+
.string()
|
|
34
|
+
.describe("Component type name present on each object, e.g. 'ModelRenderer', 'PointLight'"),
|
|
35
|
+
property: z
|
|
36
|
+
.string()
|
|
37
|
+
.describe("Property name to set, e.g. 'Tint', 'Enabled', 'LightColor' (see get_all_properties)"),
|
|
38
|
+
value: z
|
|
39
|
+
.any()
|
|
40
|
+
.describe("New value — number, bool, string, enum name, 'x,y,z' vector, color, or asset path"),
|
|
41
|
+
dryRun: z
|
|
42
|
+
.boolean()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("true = validate and report current values without changing anything. Default false"),
|
|
45
|
+
}, async (params) => {
|
|
46
|
+
const res = await bridge.send("batch_set_property", params);
|
|
47
|
+
if (!res.success) {
|
|
48
|
+
return { content: [{ type: "text", text: `Error: ${res.error}` }] };
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
// ── describe_project ─────────────────────────────────────────────
|
|
55
|
+
server.tool("describe_project", "One-call project orientation: identity (name/ident/org/type), the open scene with object count, scene and prefab file lists (capped at 50 each, Libraries/.sbox excluded), code footprint (.cs/.razor counts), custom Component types (up to 100, engine types excluded), and installed libraries. Returns a structured summary — orient here first, then get_scene_hierarchy for the scene, describe_type for components, find_broken_references for project health. Read-only", {}, async (params) => {
|
|
56
|
+
const res = await bridge.send("describe_project", params);
|
|
57
|
+
if (!res.success) {
|
|
58
|
+
return { content: [{ type: "text", text: `Error: ${res.error}` }] };
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=audit.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
|
+
* Batch operation tools (Batch 52): batch_delete, batch_add_component,
|
|
5
|
+
* batch_reparent. All follow the dryRun convention from batch_set_property.
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerBatchTools(server: McpServer, bridge: BridgeClient): void;
|
|
8
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Batch operation tools (Batch 52): batch_delete, batch_add_component,
|
|
4
|
+
* batch_reparent. All follow the dryRun convention from batch_set_property.
|
|
5
|
+
*/
|
|
6
|
+
export function registerBatchTools(server, bridge) {
|
|
7
|
+
// ── batch_delete ─────────────────────────────────────────────────
|
|
8
|
+
server.tool("batch_delete", "Delete MANY GameObjects (and their entire subtrees) in one call. ALWAYS pass dryRun:true first — it reports each object's name and child count WITHOUT deleting, so you can confirm the target list. Returns { total, succeeded, failed, dryRun, results } with per-object ok/error. Destructive and NOT undoable — get ids from find_objects or get_selected_objects and verify the dry-run before applying. Scene-mutating: refused during play mode", {
|
|
9
|
+
ids: z
|
|
10
|
+
.array(z.string())
|
|
11
|
+
.describe("GUIDs of the GameObjects to delete (subtrees included)"),
|
|
12
|
+
dryRun: z
|
|
13
|
+
.boolean()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("true = report names/child counts without deleting anything. Default false — but run a dry pass first"),
|
|
16
|
+
}, async (params) => {
|
|
17
|
+
const res = await bridge.send("batch_delete", params);
|
|
18
|
+
if (!res.success) {
|
|
19
|
+
return { content: [{ type: "text", text: `Error: ${res.error}` }] };
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
// ── batch_add_component ──────────────────────────────────────────
|
|
26
|
+
server.tool("batch_add_component", "Add one component type to MANY GameObjects in one call (e.g. BoxCollider on every crate). Skips objects that already have the component unless skipExisting:false. dryRun:true validates the type and reports per-object alreadyHas WITHOUT adding. Returns { total, succeeded, failed, skipped, dryRun, results }. Follow with batch_set_property to configure the new components. Scene-mutating: refused during play mode", {
|
|
27
|
+
ids: z
|
|
28
|
+
.array(z.string())
|
|
29
|
+
.describe("GUIDs of the target GameObjects (from find_objects or get_selected_objects)"),
|
|
30
|
+
component: z
|
|
31
|
+
.string()
|
|
32
|
+
.describe("Component type name to add, e.g. 'BoxCollider', 'PointLight' (search with list_available_components)"),
|
|
33
|
+
skipExisting: z
|
|
34
|
+
.boolean()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Skip objects that already have this component type. Default true"),
|
|
37
|
+
dryRun: z
|
|
38
|
+
.boolean()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("true = validate and report without adding anything. Default false"),
|
|
41
|
+
}, async (params) => {
|
|
42
|
+
const res = await bridge.send("batch_add_component", params);
|
|
43
|
+
if (!res.success) {
|
|
44
|
+
return { content: [{ type: "text", text: `Error: ${res.error}` }] };
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
// ── batch_reparent ───────────────────────────────────────────────
|
|
51
|
+
server.tool("batch_reparent", "Move MANY GameObjects under a new parent (or to the scene root) in one call — organize scattered props into a folder object, or regroup a level section. dryRun:true reports each object's current parent and destination WITHOUT moving. Returns { total, succeeded, failed, dryRun, keepWorldPosition, results }. Errors if parent is among ids (no cycles). Scene-mutating: refused during play mode", {
|
|
52
|
+
ids: z
|
|
53
|
+
.array(z.string())
|
|
54
|
+
.describe("GUIDs of the GameObjects to move"),
|
|
55
|
+
parent: z
|
|
56
|
+
.string()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("GUID of the new parent GameObject. Omit (or empty) to move to the scene root"),
|
|
59
|
+
keepWorldPosition: z
|
|
60
|
+
.boolean()
|
|
61
|
+
.optional()
|
|
62
|
+
.describe("Preserve each object's world position while reparenting. Default true"),
|
|
63
|
+
dryRun: z
|
|
64
|
+
.boolean()
|
|
65
|
+
.optional()
|
|
66
|
+
.describe("true = report current parents and the destination without moving anything. Default false"),
|
|
67
|
+
}, async (params) => {
|
|
68
|
+
const res = await bridge.send("batch_reparent", params);
|
|
69
|
+
if (!res.success) {
|
|
70
|
+
return { content: [{ type: "text", text: `Error: ${res.error}` }] };
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=batch.js.map
|
package/dist/tools/characters.js
CHANGED
|
@@ -56,7 +56,7 @@ export function registerCharacterTools(server, bridge) {
|
|
|
56
56
|
};
|
|
57
57
|
});
|
|
58
58
|
// ── spawn_citizen ──────────────────────────────────────────────────
|
|
59
|
-
server.tool("spawn_citizen", "Spawn an animated Citizen character: a SkinnedModelRenderer with the Citizen model, plus (by default) a CitizenAnimationHelper so it idles. PlayAnimationsInEditorScene is enabled so the idle pose shows in the editor view (screenshot-verifiable).
|
|
59
|
+
server.tool("spawn_citizen", "Spawn an animated Citizen character: a SkinnedModelRenderer with the Citizen model, plus (by default) a CitizenAnimationHelper so it idles. PlayAnimationsInEditorScene is enabled so the idle pose shows in the editor view (screenshot-verifiable). Returns { created, hasAnimator, gameObject:{ id, name, position, components, ... } } — pass gameObject.id to the follow-ups: dress_citizen, pose_citizen, set_expression, equip_model.", {
|
|
60
60
|
name: z.string().optional().describe("GameObject name (default 'Citizen')"),
|
|
61
61
|
model: z
|
|
62
62
|
.string()
|
|
@@ -110,7 +110,7 @@ export function registerCharacterTools(server, bridge) {
|
|
|
110
110
|
};
|
|
111
111
|
});
|
|
112
112
|
// ── set_bodygroup ──────────────────────────────────────────────────
|
|
113
|
-
server.tool("set_bodygroup", "Show/hide a bodygroup on a SkinnedModelRenderer (e.g. hide hands when holding a tool, swap head variants). Provide value (int index) or choice (string name).", {
|
|
113
|
+
server.tool("set_bodygroup", "Show/hide a bodygroup on a SkinnedModelRenderer (e.g. hide hands when holding a tool, swap head variants). Provide value (int index) or choice (string name). Returns { set, bodygroup } on success (errors if the object has no SkinnedModelRenderer or neither value nor choice is given); take_screenshot to verify the visual change.", {
|
|
114
114
|
id: z.string().describe("GUID of the GameObject with a SkinnedModelRenderer"),
|
|
115
115
|
name: z.string().describe("Bodygroup name"),
|
|
116
116
|
value: z.number().int().optional().describe("Bodygroup choice index"),
|
|
@@ -125,7 +125,7 @@ export function registerCharacterTools(server, bridge) {
|
|
|
125
125
|
};
|
|
126
126
|
});
|
|
127
127
|
// ── pose_citizen ───────────────────────────────────────────────────
|
|
128
|
-
server.tool("pose_citizen", "Pose a Citizen by setting CitizenAnimationHelper params (enables PlayAnimationsInEditorScene so the pose shows in-editor). Set holdType (None/Pistol/Rifle/Shotgun/HoldItem/Punch/Swing), moveStyle (Auto/Walk/Run), specialMove, sitting (bool), and/or duckLevel (0-1).", {
|
|
128
|
+
server.tool("pose_citizen", "Pose a Citizen by setting CitizenAnimationHelper params (enables PlayAnimationsInEditorScene so the pose shows in-editor). Set holdType (None/Pistol/Rifle/Shotgun/HoldItem/Punch/Swing), moveStyle (Auto/Walk/Run), specialMove, sitting (bool), and/or duckLevel (0-1). Returns { posed, changed:[...], gameObject } — changed lists which helper params were applied; take_screenshot to verify the pose.", {
|
|
129
129
|
id: z.string().describe("GUID of the Citizen GameObject (must have a CitizenAnimationHelper)"),
|
|
130
130
|
holdType: z.string().optional().describe("Hold pose, e.g. None, Pistol, Rifle, Shotgun, HoldItem"),
|
|
131
131
|
moveStyle: z.string().optional().describe("Movement style, e.g. Auto, Walk, Run"),
|
|
@@ -184,7 +184,7 @@ export function registerCharacterTools(server, bridge) {
|
|
|
184
184
|
};
|
|
185
185
|
});
|
|
186
186
|
// ── add_ragdoll ────────────────────────────────────────────────────
|
|
187
|
-
server.tool("add_ragdoll", "Add ModelPhysics to a skinned model so it becomes a ragdoll (physics-driven bones). NOTE: the ragdoll only flops in PLAY mode — it won't move in the static editor view, so this one is verified structurally, not by screenshot.", {
|
|
187
|
+
server.tool("add_ragdoll", "Add ModelPhysics to a skinned model so it becomes a ragdoll (physics-driven bones). NOTE: the ragdoll only flops in PLAY mode — it won't move in the static editor view, so this one is verified structurally, not by screenshot. Returns { ragdoll, note, gameObject } — check gameObject.components for ModelPhysics, then verify at runtime with start_play + capture_view.", {
|
|
188
188
|
id: z.string().describe("GUID of the GameObject with a SkinnedModelRenderer"),
|
|
189
189
|
motionEnabled: z
|
|
190
190
|
.boolean()
|
|
@@ -200,7 +200,7 @@ export function registerCharacterTools(server, bridge) {
|
|
|
200
200
|
};
|
|
201
201
|
});
|
|
202
202
|
// ── set_expression ─────────────────────────────────────────────────
|
|
203
|
-
server.tool("set_expression", "Set a facial morph (blendshape) on a skinned model — e.g. smile, frown, blink. Call with NO morph to list the model's available morph names (returned as availableMorphs). weight is typically 0-1.", {
|
|
203
|
+
server.tool("set_expression", "Set a facial morph (blendshape) on a skinned model — e.g. smile, frown, blink. Call with NO morph to list the model's available morph names (returned as availableMorphs). weight is typically 0-1. Returns { set, morph, weight, availableMorphs } — availableMorphs is included in every response, so a wrong name can be corrected without an extra listing call.", {
|
|
204
204
|
id: z.string().describe("GUID of the GameObject with a SkinnedModelRenderer"),
|
|
205
205
|
morph: z
|
|
206
206
|
.string()
|
|
@@ -244,7 +244,7 @@ export function registerCharacterTools(server, bridge) {
|
|
|
244
244
|
};
|
|
245
245
|
});
|
|
246
246
|
// ── set_animgraph_param ────────────────────────────────────────────
|
|
247
|
-
server.tool("set_animgraph_param", "Set an AnimationGraph parameter on a GameObject's SkinnedModelRenderer (calls Set). This drives Citizen/animgraph motion — e.g. 'move_x'/'move_y' (float), 'b_grounded'/'b_ducked' (bool), or a Vector3. Pose previews in-editor when PlayAnimationsInEditorScene is on; screenshot to verify. Param names are defined by the model's animation graph.", {
|
|
247
|
+
server.tool("set_animgraph_param", "Set an AnimationGraph parameter on a GameObject's SkinnedModelRenderer (calls Set). This drives Citizen/animgraph motion — e.g. 'move_x'/'move_y' (float), 'b_grounded'/'b_ducked' (bool), or a Vector3. Pose previews in-editor when PlayAnimationsInEditorScene is on; screenshot to verify. Param names are defined by the model's animation graph — use list_animations to check whether the model is animgraph-driven. Returns { set, param, kind, note } — kind is the type actually applied (float/int/bool/vector).", {
|
|
248
248
|
id: z.string().describe("GUID of the GameObject with a SkinnedModelRenderer"),
|
|
249
249
|
param: z.string().describe("Animgraph parameter name, e.g. 'move_x', 'b_grounded'"),
|
|
250
250
|
value: z
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { BridgeClient } from "../transport/bridge-client.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cinematics & Dialogue pack — two engine-proof, no-asset scaffolds (v1.20.0):
|
|
5
|
+
*
|
|
6
|
+
* - create_cutscene_director hand-authored camera-shot cutscene player
|
|
7
|
+
* - create_dialogue_system typewriter NPC/story dialogue (Component + Razor HUD)
|
|
8
|
+
*
|
|
9
|
+
* These are the HAND-AUTHORED cinematic path (zero assets, full C# control). The
|
|
10
|
+
* keyframed/timeline path is the MovieMaker family (add_movie_player / play_movie
|
|
11
|
+
* / stop_movie / list_movies), which wires a Sandbox.MovieMaker MoviePlayer to a
|
|
12
|
+
* .movie clip authored in the editor's Movie Maker dock.
|
|
13
|
+
*
|
|
14
|
+
* All generate self-contained, sandbox-safe, LOCAL/visual-only code; the Razor
|
|
15
|
+
* output is razor_lint-safe by construction. File/scene-mutating, so refused
|
|
16
|
+
* during play mode by the bridge dispatch.
|
|
17
|
+
*/
|
|
18
|
+
export declare function registerCinematicsTools(server: McpServer, bridge: BridgeClient): void;
|
|
19
|
+
//# sourceMappingURL=cinematics.d.ts.map
|