@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/dist/index.js +3766 -3484
- package/package.json +1 -1
- package/studio-plugin/MCPInspectorPlugin.rbxmx +12 -31
- package/studio-plugin/MCPPlugin.rbxmx +12 -31
- package/studio-plugin/src/modules/ClientBroker.ts +1 -5
- package/studio-plugin/src/modules/UI.ts +3 -1
- package/studio-plugin/src/modules/handlers/TestHandlers.ts +11 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrrxs/robloxstudio-mcp-inspector",
|
|
3
|
-
"version": "2.8.
|
|
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
|
-
--
|
|
5212
|
-
--
|
|
5213
|
-
-- only
|
|
5214
|
-
--
|
|
5215
|
-
--
|
|
5216
|
-
--
|
|
5217
|
-
|
|
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 =
|
|
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.
|
|
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,
|
|
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
|
-
--
|
|
5212
|
-
--
|
|
5213
|
-
-- only
|
|
5214
|
-
--
|
|
5215
|
-
--
|
|
5216
|
-
--
|
|
5217
|
-
|
|
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 =
|
|
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.
|
|
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,
|
|
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
|
-
|
|
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
|
-
//
|
|
193
|
-
//
|
|
194
|
-
// only
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
|
|
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:
|
|
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
|
|