@chrrxs/robloxstudio-mcp-inspector 2.8.0 → 2.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrrxs/robloxstudio-mcp-inspector",
3
- "version": "2.8.0",
3
+ "version": "2.8.1",
4
4
  "description": "Read-only MCP Server for Roblox Studio (fork of boshyxd/robloxstudio-mcp-inspector with per-peer execute_luau fixes baked in)",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -154,7 +154,6 @@ local function setupClientBroker()
154
154
  }
155
155
  return _arg0
156
156
  end
157
- print("[MCPFork] client broker ready")
158
157
  end
159
158
  local proxyByPlayer = {}
160
159
  local function pollProxy(proxyId, player, rf)
@@ -238,7 +237,6 @@ local function registerProxy(player, rf)
238
237
  role = assigned,
239
238
  }
240
239
  proxyByPlayer[_player_1] = _arg1
241
- print(`[MCPFork] proxy {assigned} -> {player.Name}`)
242
240
  task.spawn(pollProxy, proxyId, player, rf)
243
241
  end
244
242
  local function startEditProxyLoop()
@@ -246,13 +244,12 @@ local function startEditProxyLoop()
246
244
  local proxyId = HttpService:GenerateGUID(false)
247
245
  local ok, res = postJson("/ready", {
248
246
  instanceId = proxyId,
249
- role = "edit",
247
+ role = "edit-proxy",
250
248
  })
251
249
  if not ok or not res or not res.Success then
252
250
  warn("[MCPFork] edit-proxy register failed")
253
251
  return nil
254
252
  end
255
- print("[MCPFork] edit-proxy ready (stop-playtest interceptor)")
256
253
  while true do
257
254
  local okPoll, pollRes = pcall(function()
258
255
  return HttpService:RequestAsync({
@@ -323,7 +320,6 @@ local function setupServerBroker()
323
320
  table.clear(proxyByPlayer)
324
321
  end)
325
322
  startEditProxyLoop()
326
- print("[MCPFork] server broker ready")
327
323
  end
328
324
  return {
329
325
  MCP_URL = MCP_URL,
@@ -5208,31 +5204,16 @@ local function startPlaytest(requestData)
5208
5204
  }
5209
5205
  end
5210
5206
  local function stopPlaytest(_requestData)
5211
- -- Stop requests are normally intercepted by the server-peer edit-proxy in
5212
- -- modules/ClientBroker - that proxy runs inside the play server DM, the
5213
- -- only DM where StudioTestService:EndTest is legal. If we reach this
5214
- -- handler the broker either hasn't started yet or there's no active
5215
- -- playtest. Try EndTest directly as a fallback (works for manually
5216
- -- started playtests where the server-peer plugin happens to be polling).
5217
- local endTest = StudioTestService
5218
- local endOk, endErr = pcall(function()
5219
- endTest:EndTest("stopped_by_mcp")
5220
- end)
5221
- if endOk then
5222
- local _object = {
5223
- success = true,
5224
- }
5225
- local _left = "output"
5226
- local _array = {}
5227
- local _length = #_array
5228
- table.move(outputBuffer, 1, #outputBuffer, _length + 1, _array)
5229
- _object[_left] = _array
5230
- _object.outputCount = #outputBuffer
5231
- _object.message = "Playtest stopped via StudioTestService."
5232
- return _object
5233
- end
5207
+ -- Server-side routing (tools/index.ts:stopPlaytest) sends /api/stop-playtest
5208
+ -- to the role="edit-proxy" instance whenever one is registered. This handler
5209
+ -- is only reached when there's no edit-proxy - i.e. no active playtest, or
5210
+ -- the play DMs haven't completed plugin auto-activation yet. Calling
5211
+ -- StudioTestService:EndTest from the edit DM is illegal ("can only be
5212
+ -- called from the server DataModel of a running Studio play session"), so
5213
+ -- don't try - return a clean "no active playtest" response instead.
5234
5214
  return {
5235
- error = `stopPlaytest fell through to edit DM (broker should have handled it). EndTest reported: {tostring(endErr)}`,
5215
+ error = "No active playtest to stop (edit-proxy not registered).",
5216
+ hint = "If a playtest is running, the play-server DM may not have completed plugin auto-activation yet. " .. "Wait a moment and retry, or call execute_luau target=server with StudioTestService:EndTest as a manual fallback.",
5236
5217
  }
5237
5218
  end
5238
5219
  local function getPlaytestOutput(_requestData)
@@ -5360,7 +5341,7 @@ return {
5360
5341
  <Properties>
5361
5342
  <string name="Name">State</string>
5362
5343
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
5363
- local CURRENT_VERSION = "2.8.0"
5344
+ local CURRENT_VERSION = "2.8.1"
5364
5345
  local MAX_CONNECTIONS = 5
5365
5346
  local BASE_PORT = 58741
5366
5347
  local activeTabIndex = 0
@@ -5674,7 +5655,7 @@ local function updateTabLabel(connIndex)
5674
5655
  end
5675
5656
  local function init(pluginRef)
5676
5657
  local CURRENT_VERSION = State.CURRENT_VERSION
5677
- local screenGui = pluginRef:CreateDockWidgetPluginGuiAsync("MCPServerInterface", DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, false, false, 300, 260, 260, 200))
5658
+ local screenGui = pluginRef:CreateDockWidgetPluginGuiAsync("MCPServerInterface", DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, false, true, 300, 260, 260, 200))
5678
5659
  screenGui.Title = `MCP Server v{CURRENT_VERSION}`
5679
5660
  local mainFrame = Instance.new("Frame")
5680
5661
  mainFrame.Size = UDim2.new(1, 0, 1, 0)
@@ -154,7 +154,6 @@ local function setupClientBroker()
154
154
  }
155
155
  return _arg0
156
156
  end
157
- print("[MCPFork] client broker ready")
158
157
  end
159
158
  local proxyByPlayer = {}
160
159
  local function pollProxy(proxyId, player, rf)
@@ -238,7 +237,6 @@ local function registerProxy(player, rf)
238
237
  role = assigned,
239
238
  }
240
239
  proxyByPlayer[_player_1] = _arg1
241
- print(`[MCPFork] proxy {assigned} -> {player.Name}`)
242
240
  task.spawn(pollProxy, proxyId, player, rf)
243
241
  end
244
242
  local function startEditProxyLoop()
@@ -246,13 +244,12 @@ local function startEditProxyLoop()
246
244
  local proxyId = HttpService:GenerateGUID(false)
247
245
  local ok, res = postJson("/ready", {
248
246
  instanceId = proxyId,
249
- role = "edit",
247
+ role = "edit-proxy",
250
248
  })
251
249
  if not ok or not res or not res.Success then
252
250
  warn("[MCPFork] edit-proxy register failed")
253
251
  return nil
254
252
  end
255
- print("[MCPFork] edit-proxy ready (stop-playtest interceptor)")
256
253
  while true do
257
254
  local okPoll, pollRes = pcall(function()
258
255
  return HttpService:RequestAsync({
@@ -323,7 +320,6 @@ local function setupServerBroker()
323
320
  table.clear(proxyByPlayer)
324
321
  end)
325
322
  startEditProxyLoop()
326
- print("[MCPFork] server broker ready")
327
323
  end
328
324
  return {
329
325
  MCP_URL = MCP_URL,
@@ -5208,31 +5204,16 @@ local function startPlaytest(requestData)
5208
5204
  }
5209
5205
  end
5210
5206
  local function stopPlaytest(_requestData)
5211
- -- Stop requests are normally intercepted by the server-peer edit-proxy in
5212
- -- modules/ClientBroker - that proxy runs inside the play server DM, the
5213
- -- only DM where StudioTestService:EndTest is legal. If we reach this
5214
- -- handler the broker either hasn't started yet or there's no active
5215
- -- playtest. Try EndTest directly as a fallback (works for manually
5216
- -- started playtests where the server-peer plugin happens to be polling).
5217
- local endTest = StudioTestService
5218
- local endOk, endErr = pcall(function()
5219
- endTest:EndTest("stopped_by_mcp")
5220
- end)
5221
- if endOk then
5222
- local _object = {
5223
- success = true,
5224
- }
5225
- local _left = "output"
5226
- local _array = {}
5227
- local _length = #_array
5228
- table.move(outputBuffer, 1, #outputBuffer, _length + 1, _array)
5229
- _object[_left] = _array
5230
- _object.outputCount = #outputBuffer
5231
- _object.message = "Playtest stopped via StudioTestService."
5232
- return _object
5233
- end
5207
+ -- Server-side routing (tools/index.ts:stopPlaytest) sends /api/stop-playtest
5208
+ -- to the role="edit-proxy" instance whenever one is registered. This handler
5209
+ -- is only reached when there's no edit-proxy - i.e. no active playtest, or
5210
+ -- the play DMs haven't completed plugin auto-activation yet. Calling
5211
+ -- StudioTestService:EndTest from the edit DM is illegal ("can only be
5212
+ -- called from the server DataModel of a running Studio play session"), so
5213
+ -- don't try - return a clean "no active playtest" response instead.
5234
5214
  return {
5235
- error = `stopPlaytest fell through to edit DM (broker should have handled it). EndTest reported: {tostring(endErr)}`,
5215
+ error = "No active playtest to stop (edit-proxy not registered).",
5216
+ hint = "If a playtest is running, the play-server DM may not have completed plugin auto-activation yet. " .. "Wait a moment and retry, or call execute_luau target=server with StudioTestService:EndTest as a manual fallback.",
5236
5217
  }
5237
5218
  end
5238
5219
  local function getPlaytestOutput(_requestData)
@@ -5360,7 +5341,7 @@ return {
5360
5341
  <Properties>
5361
5342
  <string name="Name">State</string>
5362
5343
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
5363
- local CURRENT_VERSION = "2.8.0"
5344
+ local CURRENT_VERSION = "2.8.1"
5364
5345
  local MAX_CONNECTIONS = 5
5365
5346
  local BASE_PORT = 58741
5366
5347
  local activeTabIndex = 0
@@ -5674,7 +5655,7 @@ local function updateTabLabel(connIndex)
5674
5655
  end
5675
5656
  local function init(pluginRef)
5676
5657
  local CURRENT_VERSION = State.CURRENT_VERSION
5677
- local screenGui = pluginRef:CreateDockWidgetPluginGuiAsync("MCPServerInterface", DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, false, false, 300, 260, 260, 200))
5658
+ local screenGui = pluginRef:CreateDockWidgetPluginGuiAsync("MCPServerInterface", DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, false, true, 300, 260, 260, 200))
5678
5659
  screenGui.Title = `MCP Server v{CURRENT_VERSION}`
5679
5660
  local mainFrame = Instance.new("Frame")
5680
5661
  mainFrame.Size = UDim2.new(1, 0, 1, 0)
@@ -94,7 +94,6 @@ function setupClientBroker() {
94
94
  }
95
95
  return identity<ExecuteResult>({ success: false, error: tostring(result) });
96
96
  };
97
- print("[MCPFork] client broker ready");
98
97
  }
99
98
 
100
99
  const proxyByPlayer = new Map<Player, ProxyEntry>();
@@ -141,19 +140,17 @@ function registerProxy(player: Player, rf: RemoteFunction) {
141
140
  const body = HttpService.JSONDecode(res.Body) as ReadyResponseBody;
142
141
  const assigned = body.assignedRole ?? "client";
143
142
  proxyByPlayer.set(player, { instanceId: proxyId, role: assigned });
144
- print(`[MCPFork] proxy ${assigned} -> ${player.Name}`);
145
143
  task.spawn(pollProxy, proxyId, player, rf);
146
144
  }
147
145
 
148
146
  function startEditProxyLoop() {
149
147
  task.spawn(() => {
150
148
  const proxyId = HttpService.GenerateGUID(false);
151
- const [ok, res] = postJson("/ready", { instanceId: proxyId, role: "edit" });
149
+ const [ok, res] = postJson("/ready", { instanceId: proxyId, role: "edit-proxy" });
152
150
  if (!ok || !res || !res.Success) {
153
151
  warn("[MCPFork] edit-proxy register failed");
154
152
  return;
155
153
  }
156
- print("[MCPFork] edit-proxy ready (stop-playtest interceptor)");
157
154
  while (true) {
158
155
  const [okPoll, pollRes] = pcall(() =>
159
156
  HttpService.RequestAsync({
@@ -210,7 +207,6 @@ function setupServerBroker() {
210
207
  proxyByPlayer.clear();
211
208
  });
212
209
  startEditProxyLoop();
213
- print("[MCPFork] server broker ready");
214
210
  }
215
211
 
216
212
  export = {
@@ -226,7 +226,9 @@ function init(pluginRef: Plugin) {
226
226
 
227
227
  const screenGui = pluginRef.CreateDockWidgetPluginGuiAsync(
228
228
  "MCPServerInterface",
229
- new DockWidgetPluginGuiInfo(Enum.InitialDockState.Float, false, false, 300, 260, 260, 200),
229
+ // 3rd arg (initialEnabledShouldOverrideRestore=true) forces the dock closed
230
+ // at every Studio launch. User can still open via the toolbar button.
231
+ new DockWidgetPluginGuiInfo(Enum.InitialDockState.Float, false, true, 300, 260, 260, 200),
230
232
  );
231
233
  (screenGui as unknown as { Title: string }).Title = `MCP Server v${CURRENT_VERSION}`;
232
234
 
@@ -189,27 +189,18 @@ function startPlaytest(requestData: Record<string, unknown>) {
189
189
  }
190
190
 
191
191
  function stopPlaytest(_requestData: Record<string, unknown>) {
192
- // Stop requests are normally intercepted by the server-peer edit-proxy in
193
- // modules/ClientBroker - that proxy runs inside the play server DM, the
194
- // only DM where StudioTestService:EndTest is legal. If we reach this
195
- // handler the broker either hasn't started yet or there's no active
196
- // playtest. Try EndTest directly as a fallback (works for manually
197
- // started playtests where the server-peer plugin happens to be polling).
198
- const endTest = StudioTestService as unknown as Instance & { EndTest(reason: string): void };
199
- const [endOk, endErr] = pcall(() => {
200
- endTest.EndTest("stopped_by_mcp");
201
- });
202
- if (endOk) {
203
- return {
204
- success: true,
205
- output: [...outputBuffer],
206
- outputCount: outputBuffer.size(),
207
- message: "Playtest stopped via StudioTestService.",
208
- };
209
- }
210
-
192
+ // Server-side routing (tools/index.ts:stopPlaytest) sends /api/stop-playtest
193
+ // to the role="edit-proxy" instance whenever one is registered. This handler
194
+ // is only reached when there's no edit-proxy - i.e. no active playtest, or
195
+ // the play DMs haven't completed plugin auto-activation yet. Calling
196
+ // StudioTestService:EndTest from the edit DM is illegal ("can only be
197
+ // called from the server DataModel of a running Studio play session"), so
198
+ // don't try - return a clean "no active playtest" response instead.
211
199
  return {
212
- error: `stopPlaytest fell through to edit DM (broker should have handled it). EndTest reported: ${tostring(endErr)}`,
200
+ error: "No active playtest to stop (edit-proxy not registered).",
201
+ hint:
202
+ "If a playtest is running, the play-server DM may not have completed plugin auto-activation yet. " +
203
+ "Wait a moment and retry, or call execute_luau target=server with StudioTestService:EndTest as a manual fallback.",
213
204
  };
214
205
  }
215
206