@el4cteo/rbx-studio-mcp 0.5.9 → 0.6.1

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/README.md CHANGED
@@ -83,7 +83,7 @@ Two things to watch: a playtest connects a second session, so pass `studioId` an
83
83
 
84
84
  ## The console panel
85
85
 
86
- Every call is logged with how long it took. Below the header is a command line — type a command, or type a sentence and a coding agent answers it.
86
+ Every call is logged with how long it took. At the foot of the panel is a command line — type a command, or type a sentence and a coding agent answers it.
87
87
 
88
88
  | | |
89
89
  |---|---|
@@ -91,12 +91,12 @@ Every call is logged with how long it took. Below the header is a command line
91
91
  | `doctor` | check the setup |
92
92
  | `status` `version` `place` `clients` | what this session is |
93
93
  | `studios` `use <n>` | which Studio window calls go to |
94
- | `theme [name]` `visuals` `log [level]` `clear` `copy` | the panel |
94
+ | `theme [name]` `visuals` `autoopen [on\|off]` `log [level]` `clear` `copy` | the panel |
95
95
  | `port [n]` `reconnect` | the connection |
96
96
  | `agent [use <id>\|new]` `stop` | which agent runs your prompts |
97
97
  | anything else | sent to that agent |
98
98
 
99
- Arrows walk the history, Tab completes.
99
+ Click the bar and every command is listed with what it does. Keep typing to filter, scroll for the rest, click one to fill it in.
100
100
 
101
101
  **Prompts start a real agent** — whichever you have on PATH: Claude Code, Codex, opencode, Gemini, Cursor, Amp, Qwen Code, Factory Droid, goose, Copilot CLI, Aider, Crush, DeepSeek Harness. It runs headless, drives the same Studio, and its work appears in the log. It is a separate session from your terminal, billed separately, and allowed the `rbx-studio` tools only. `stop` cancels it.
102
102
 
@@ -111,15 +111,23 @@ Eight themes behind the tab on the right edge. Your pick is remembered.
111
111
 
112
112
  ## DeepSeek Harness (dsh)
113
113
 
114
- This server registers as a dsh plugin. The row ships in the package, at
115
- `node_modules/@el4cteo/rbx-studio-mcp/config/dsh.cordis.yml`:
116
-
117
- ```sh
118
- dsh --profile headless --patch <that path> "add a spawn point"
114
+ This server registers as a dsh plugin. Append this row to `$DSH_HOME/cordis.patch.yml`,
115
+ or to `$DSH_HOME/profiles/<name>/cordis.patch.yml` for one profile only:
116
+
117
+ ```yaml
118
+ - insert:
119
+ - id: mcp-rbx-studio
120
+ name: '@deepseek-ai/dsh-mcp-client'
121
+ config:
122
+ serverName: rbx-studio
123
+ transport: stdio
124
+ command: npx
125
+ args: ['-y', '@el4cteo/rbx-studio-mcp']
126
+ cwd: !!js process.cwd()
119
127
  ```
120
128
 
121
- To keep it, append the row to `$DSH_HOME/profiles/<name>/cordis.patch.yml` for one
122
- profile, or `$DSH_HOME/cordis.patch.yml` for all of them. Needs `DEEPSEEK_API_KEY`.
129
+ Then `dsh --profile headless "what is in workspace"`. Needs `DEEPSEEK_API_KEY`.
130
+ The same row, commented, is in `config/dsh.cordis.yml` for use with `dsh --patch`.
123
131
 
124
132
  ## Security
125
133
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@el4cteo/rbx-studio-mcp",
3
- "version": "0.5.9",
3
+ "version": "0.6.1",
4
4
  "description": "MCP server for Roblox Studio. 31 tools, push-based SSE bridge, editor-safe script edits, one-step undo.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -40,6 +40,9 @@ export type Hooks = {
40
40
  -- has to outlive the session is handed back to the script that can persist it.
41
41
  savePort: (number) -> (),
42
42
  saveTheme: (string) -> (),
43
+ -- Whether the panel may open itself on load, and the setter for it.
44
+ autoOpen: () -> boolean,
45
+ saveAutoOpen: (boolean) -> (),
43
46
  -- The transport's own view of the connection, which the console only ever
44
47
  -- receives second-hand as a string to display.
45
48
  status: () -> string,
@@ -247,6 +250,63 @@ define({
247
250
  end,
248
251
  })
249
252
 
253
+ define({
254
+ name = "autoopen",
255
+ usage = "autoopen [on|off]",
256
+ summary = "let this panel open itself, or only ever from the toolbar",
257
+ run = function(args)
258
+ local current = hooks
259
+ if current == nil then
260
+ return
261
+ end
262
+
263
+ local wanted = args[1]
264
+ if wanted == nil then
265
+ Console.log(
266
+ "dim",
267
+ if current.autoOpen()
268
+ then "autoopen on -- the panel opens with the place, and with Play"
269
+ else "autoopen off -- the panel opens only from the toolbar button"
270
+ )
271
+ return
272
+ end
273
+
274
+ local value: boolean
275
+ if wanted == "on" then
276
+ value = true
277
+ elseif wanted == "off" then
278
+ value = false
279
+ else
280
+ Console.log("error", string.format("%q is not on or off", wanted), "autoopen [on|off]")
281
+ return
282
+ end
283
+
284
+ if value == current.autoOpen() then
285
+ Console.log("dim", string.format("already autoopen %s", wanted))
286
+ return
287
+ end
288
+
289
+ current.saveAutoOpen(value)
290
+ --[[
291
+ Said plainly, because nothing about it can be seen from here.
292
+
293
+ A dock widget's initial state is decided when Studio creates it, and
294
+ this one already exists -- so the change shows up at the next load,
295
+ not now. A setting that appears to do nothing is a setting the user
296
+ runs again, and then a third time, before deciding it is broken.
297
+ ]]
298
+ if value then
299
+ Console.log("ok", "autoopen on", "the panel will come back on its own")
300
+ else
301
+ Console.log(
302
+ "ok",
303
+ "autoopen off",
304
+ "from the next place or playtest, open it from the toolbar"
305
+ )
306
+ end
307
+ end,
308
+ })
309
+
250
310
  define({
251
311
  name = "place",
252
312
  usage = "place",
@@ -9,7 +9,7 @@
9
9
 
10
10
  local Config = {}
11
11
 
12
- Config.PLUGIN_VERSION = "0.5.9"
12
+ Config.PLUGIN_VERSION = "0.6.1"
13
13
 
14
14
  -- Fingerprint of plugin/src, stamped in by scripts/build-plugin.mjs. The server
15
15
  -- computes the same hash from its own copy of the sources and compares, so a
@@ -47,6 +47,19 @@ local SETTING_AUTOCONNECT = "autoConnect"
47
47
  local SETTING_FORCE_POLL = "forcePoll"
48
48
  local SETTING_THEME = "theme"
49
49
  local SETTING_WIDGET_OPEN = "widgetOpen"
50
+ --[[
51
+ Whether the panel is allowed to come up on its own at all.
52
+
53
+ Separate from `widgetOpen`, which is where the user last left it. That one
54
+ answers "was it open?"; this one answers "may it open itself?", and they are
55
+ different questions -- someone who wants the panel there when they ask for it
56
+ and nowhere else has no way to say so with a single remembered flag, because
57
+ opening it once would arm it for every load afterwards.
58
+
59
+ Off means the toolbar button is the only thing that opens it: not a place
60
+ being opened, not a Studio launch, not pressing Play. Set by `autoopen off`.
61
+ ]]
62
+ local SETTING_AUTO_OPEN = "autoOpen"
50
63
  local SETTING_WIDGET_SIZE = "widgetSize"
51
64
  local SETTING_WIDGET_TRACE = "widgetTrace"
52
65
 
@@ -210,6 +223,27 @@ button.ClickableWhenViewportHidden = true
210
223
  local storedOpen = plugin:GetSetting(SETTING_WIDGET_OPEN)
211
224
  local wantOpen = if typeof(storedOpen) == "boolean" then storedOpen else true
212
225
 
226
+ --[[
227
+ `autoopen off` means this load does not put the panel on screen.
228
+
229
+ Every DataModel, deliberately. The first version of this only covered the
230
+ playtest, on the reading that a window over the game view was the complaint
231
+ -- but a panel that reappears every time a place is opened is the same
232
+ complaint arriving through the other door, and one switch for "open yourself"
233
+ is easier to hold in your head than two.
234
+
235
+ Read here rather than acted on later because a dock widget's initial state is
236
+ fixed when it is created: bringing it up and hiding it again would flash a
237
+ window on screen, which is the thing being asked for less of. `widgetOpen` is
238
+ left exactly as it was, so turning this back on restores the panel to however
239
+ it was last left rather than to a default.
240
+ ]]
241
+ local storedAutoOpen = plugin:GetSetting(SETTING_AUTO_OPEN)
242
+ local autoOpen = if typeof(storedAutoOpen) == "boolean" then storedAutoOpen else true
243
+ if not autoOpen then
244
+ wantOpen = false
245
+ end
246
+
213
247
  local floatWidth, floatHeight = 560, 320
214
248
  local storedSize = plugin:GetSetting(SETTING_WIDGET_SIZE)
215
249
  if typeof(storedSize) == "table" then
@@ -435,6 +469,15 @@ Commands.setup({
435
469
  saveTheme = function(id)
436
470
  plugin:SetSetting(SETTING_THEME, id)
437
471
  end,
472
+ autoOpen = function()
473
+ return autoOpen
474
+ end,
475
+ saveAutoOpen = function(value)
476
+ -- The live copy moves too, so `autoopen` with no argument reports what
477
+ -- was just set rather than what the session started with.
478
+ autoOpen = value
479
+ plugin:SetSetting(SETTING_AUTO_OPEN, value)
480
+ end,
438
481
  status = function()
439
482
  return currentStatus
440
483
  end,