@chrrxs/robloxstudio-mcp-inspector 2.23.0 → 2.23.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
CHANGED
|
@@ -3856,8 +3856,8 @@ var init_http_server = __esm({
|
|
|
3856
3856
|
solo_playtest: (tools, body) => tools.soloPlaytest(body.action, body.mode, body.timeout, body.instance_id),
|
|
3857
3857
|
start_playtest: (tools, body) => tools.startPlaytest(body.mode, body.numPlayers, body.instance_id),
|
|
3858
3858
|
stop_playtest: (tools, body) => tools.stopPlaytest(body.instance_id),
|
|
3859
|
-
multiplayer_playtest: (tools, body) => tools.multiplayerPlaytest(body.action, body.numPlayers, body.target, body.testArgs, body.value, body.timeout, body.instance_id
|
|
3860
|
-
multiplayer_test_start: (tools, body) => tools.multiplayerTestStart(body.numPlayers, body.testArgs, body.timeout, body.instance_id
|
|
3859
|
+
multiplayer_playtest: (tools, body) => tools.multiplayerPlaytest(body.action, body.numPlayers, body.target, body.testArgs, body.value, body.timeout, body.instance_id),
|
|
3860
|
+
multiplayer_test_start: (tools, body) => tools.multiplayerTestStart(body.numPlayers, body.testArgs, body.timeout, body.instance_id),
|
|
3861
3861
|
multiplayer_test_state: (tools, body) => tools.multiplayerTestState(body.instance_id),
|
|
3862
3862
|
multiplayer_test_add_players: (tools, body) => tools.multiplayerTestAddPlayers(body.numPlayers, body.timeout, body.instance_id),
|
|
3863
3863
|
multiplayer_test_leave_client: (tools, body) => tools.multiplayerTestLeaveClient(body.target, body.timeout, body.instance_id),
|
|
@@ -7883,16 +7883,6 @@ var init_png_encoder = __esm({
|
|
|
7883
7883
|
import * as fs3 from "fs";
|
|
7884
7884
|
import * as os3 from "os";
|
|
7885
7885
|
import * as path5 from "path";
|
|
7886
|
-
function multiplayerStopDisabledBody() {
|
|
7887
|
-
return {
|
|
7888
|
-
success: false,
|
|
7889
|
-
error: "multiplayer_stop_disabled",
|
|
7890
|
-
message: MULTIPLAYER_STOP_DISABLED_MESSAGE,
|
|
7891
|
-
reason: "StudioTestService:EndTest does not reliably end StudioTestService multiplayer sessions from MCP right now.",
|
|
7892
|
-
manualCleanupRequired: true,
|
|
7893
|
-
recoveryHint: "Close the Roblox Studio multiplayer test windows manually."
|
|
7894
|
-
};
|
|
7895
|
-
}
|
|
7896
7886
|
function normalizeCreatorStoreSearch(assetType, query) {
|
|
7897
7887
|
if (!CREATOR_STORE_SEARCH_TYPES.has(assetType)) {
|
|
7898
7888
|
throw new Error(`search_assets assetType must be one of: ${Array.from(CREATOR_STORE_SEARCH_TYPES).join(", ")}`);
|
|
@@ -8548,7 +8538,7 @@ end
|
|
|
8548
8538
|
error("Unsupported device simulator operation: " .. tostring(opts.operation), 0)
|
|
8549
8539
|
`.trim();
|
|
8550
8540
|
}
|
|
8551
|
-
var MAX_INLINE_IMAGE_BYTES, DEFAULT_ASSET_AUDIO_PREVIEWS, MAX_ASSET_AUDIO_PREVIEWS, MAX_INLINE_AUDIO_PREVIEW_BYTES, MAX_INLINE_AUDIO_PREVIEW_TOTAL_BYTES, DEFAULT_ASSET_PREVIEW_DEPTH, MAX_ASSET_PREVIEW_HIERARCHY_NODES, MAX_SEARCH_ASSET_DESCRIPTION_LENGTH, ROBLOX_CREATOR_USER_ID, MAX_DEVICE_MATRIX_ENTRIES, MAX_NETWORK_PACKET_LOSS_PERCENT, STUDIO_ASSISTANT_SOURCE_IMAGE_LABEL, CREATOR_STORE_SEARCH_TYPES, CREATOR_STORE_SORT_CATEGORIES,
|
|
8541
|
+
var MAX_INLINE_IMAGE_BYTES, DEFAULT_ASSET_AUDIO_PREVIEWS, MAX_ASSET_AUDIO_PREVIEWS, MAX_INLINE_AUDIO_PREVIEW_BYTES, MAX_INLINE_AUDIO_PREVIEW_TOTAL_BYTES, DEFAULT_ASSET_PREVIEW_DEPTH, MAX_ASSET_PREVIEW_HIERARCHY_NODES, MAX_SEARCH_ASSET_DESCRIPTION_LENGTH, ROBLOX_CREATOR_USER_ID, MAX_DEVICE_MATRIX_ENTRIES, MAX_NETWORK_PACKET_LOSS_PERCENT, STUDIO_ASSISTANT_SOURCE_IMAGE_LABEL, CREATOR_STORE_SEARCH_TYPES, CREATOR_STORE_SORT_CATEGORIES, NETWORK_PROFILE_KEYS, NETWORK_PROFILES, ZERO_NETWORK_PROFILE, SIMULATION_PERSISTENCE_NOTES, RobloxStudioTools;
|
|
8552
8542
|
var init_tools = __esm({
|
|
8553
8543
|
"../core/dist/tools/index.js"() {
|
|
8554
8544
|
"use strict";
|
|
@@ -8596,8 +8586,6 @@ var init_tools = __esm({
|
|
|
8596
8586
|
"UpdatedTime",
|
|
8597
8587
|
"Ratings"
|
|
8598
8588
|
]);
|
|
8599
|
-
MULTIPLAYER_FORCE_REQUIRED_MESSAGE = "StudioTestService multiplayer stop is currently disabled because StudioTestService:EndTest is broken for this flow. Pass force=true only if you understand you must manually close the multiplayer test windows afterward.";
|
|
8600
|
-
MULTIPLAYER_STOP_DISABLED_MESSAGE = "Multiplayer playtest stop/end is disabled because StudioTestService:EndTest is currently broken for this flow. Manually close the Studio multiplayer test windows instead.";
|
|
8601
8589
|
NETWORK_PROFILE_KEYS = [
|
|
8602
8590
|
"InboundNetworkMinDelayMs",
|
|
8603
8591
|
"OutboundNetworkMinDelayMs",
|
|
@@ -10834,7 +10822,7 @@ ${code}`
|
|
|
10834
10822
|
}
|
|
10835
10823
|
return { ok: false, roles: this._rolesForInstance(instanceId), timedOut: true, phase: lastPhase };
|
|
10836
10824
|
}
|
|
10837
|
-
async multiplayerPlaytest(action, numPlayers, target, testArgs, value, timeout, instance_id
|
|
10825
|
+
async multiplayerPlaytest(action, numPlayers, target, testArgs, value, timeout, instance_id) {
|
|
10838
10826
|
if (action !== "start" && action !== "status" && action !== "add_players" && action !== "leave_client" && action !== "end") {
|
|
10839
10827
|
throw new Error("multiplayer_playtest requires action=start|status|add_players|leave_client|end");
|
|
10840
10828
|
}
|
|
@@ -10843,7 +10831,6 @@ ${code}`
|
|
|
10843
10831
|
return {
|
|
10844
10832
|
phase: state.phase,
|
|
10845
10833
|
roles: Array.isArray(state.peers) ? state.peers.map((peer) => peer.role).filter((role) => typeof role === "string") : [],
|
|
10846
|
-
clientRoles: Array.isArray(state.clientRoles) ? state.clientRoles : [],
|
|
10847
10834
|
playerCount: typeof state.playerCount === "number" ? state.playerCount : void 0,
|
|
10848
10835
|
error: typeof state.error === "string" ? state.error : void 0
|
|
10849
10836
|
};
|
|
@@ -10856,102 +10843,87 @@ ${code}`
|
|
|
10856
10843
|
});
|
|
10857
10844
|
}
|
|
10858
10845
|
if (action === "start") {
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
action,
|
|
10863
|
-
error: "multiplayer_force_required",
|
|
10864
|
-
message: MULTIPLAYER_FORCE_REQUIRED_MESSAGE,
|
|
10865
|
-
requiresForce: true,
|
|
10866
|
-
manualCleanupRequired: true
|
|
10867
|
-
});
|
|
10868
|
-
}
|
|
10869
|
-
const body = this._parseTextResult(await this.multiplayerTestStart(numPlayers, testArgs, timeout, instance_id, force));
|
|
10870
|
-
const state = body.state && typeof body.state === "object" ? body.state : {};
|
|
10871
|
-
const launched = body.success === true && body.ready === true;
|
|
10846
|
+
const body2 = this._parseTextResult(await this.multiplayerTestStart(numPlayers, testArgs, timeout, instance_id));
|
|
10847
|
+
const state = body2.state && typeof body2.state === "object" ? body2.state : {};
|
|
10848
|
+
const launched = body2.success === true && body2.ready === true;
|
|
10872
10849
|
return this._textResult(launched ? {
|
|
10873
10850
|
success: true,
|
|
10874
10851
|
action,
|
|
10875
|
-
message: "Multiplayer playtest started.
|
|
10876
|
-
|
|
10877
|
-
manualCleanupRequired: true,
|
|
10878
|
-
roles: Array.isArray(body.roles) ? body.roles : void 0,
|
|
10879
|
-
clientRoles: Array.isArray(state.clientRoles) ? state.clientRoles : void 0,
|
|
10852
|
+
message: "Multiplayer playtest started.",
|
|
10853
|
+
roles: Array.isArray(body2.roles) ? body2.roles : void 0,
|
|
10880
10854
|
playerCount: typeof state.playerCount === "number" ? state.playerCount : void 0
|
|
10881
10855
|
} : {
|
|
10882
10856
|
success: false,
|
|
10883
10857
|
action,
|
|
10884
|
-
error:
|
|
10885
|
-
message:
|
|
10886
|
-
|
|
10887
|
-
roles: Array.isArray(body.roles) ? body.roles : void 0
|
|
10858
|
+
error: body2.error ?? body2.wait?.error ?? "multiplayer_start_not_detected",
|
|
10859
|
+
message: body2.success === true ? "Multiplayer playtest start was requested, but MCP did not detect the required server/client peers before timeout." : body2.message ?? "Multiplayer playtest did not start.",
|
|
10860
|
+
roles: Array.isArray(body2.roles) ? body2.roles : void 0
|
|
10888
10861
|
});
|
|
10889
10862
|
}
|
|
10890
10863
|
if (action === "add_players") {
|
|
10891
|
-
const
|
|
10892
|
-
const state =
|
|
10893
|
-
const success =
|
|
10864
|
+
const body2 = this._parseTextResult(await this.multiplayerTestAddPlayers(numPlayers, timeout, instance_id));
|
|
10865
|
+
const state = body2.state && typeof body2.state === "object" ? body2.state : {};
|
|
10866
|
+
const success = body2.success === true && body2.ready === true;
|
|
10894
10867
|
return this._textResult(success ? {
|
|
10895
10868
|
success: true,
|
|
10896
10869
|
action,
|
|
10897
10870
|
message: "Players added.",
|
|
10898
|
-
roles: Array.isArray(
|
|
10899
|
-
clientRoles: Array.isArray(state.clientRoles) ? state.clientRoles : void 0,
|
|
10871
|
+
roles: Array.isArray(body2.roles) ? body2.roles : void 0,
|
|
10900
10872
|
playerCount: typeof state.playerCount === "number" ? state.playerCount : void 0
|
|
10901
10873
|
} : {
|
|
10902
10874
|
success: false,
|
|
10903
10875
|
action,
|
|
10904
|
-
error:
|
|
10905
|
-
message:
|
|
10906
|
-
roles: Array.isArray(
|
|
10876
|
+
error: body2.error ?? "add_players_failed",
|
|
10877
|
+
message: body2.success === true ? "Players did not finish joining before timeout." : body2.message ?? "Players were not added.",
|
|
10878
|
+
roles: Array.isArray(body2.roles) ? body2.roles : void 0
|
|
10907
10879
|
});
|
|
10908
10880
|
}
|
|
10909
10881
|
if (action === "leave_client") {
|
|
10910
|
-
const
|
|
10911
|
-
return this._textResult(
|
|
10882
|
+
const body2 = this._parseTextResult(await this.multiplayerTestLeaveClient(target ?? "client-1", timeout, instance_id));
|
|
10883
|
+
return this._textResult(body2.success === true && body2.left === true ? {
|
|
10912
10884
|
success: true,
|
|
10913
10885
|
action,
|
|
10914
10886
|
message: "Client left.",
|
|
10915
|
-
roles: Array.isArray(
|
|
10887
|
+
roles: Array.isArray(body2.roles) ? body2.roles : void 0
|
|
10916
10888
|
} : {
|
|
10917
10889
|
success: false,
|
|
10918
10890
|
action,
|
|
10919
|
-
error:
|
|
10920
|
-
message:
|
|
10921
|
-
roles: Array.isArray(
|
|
10891
|
+
error: body2.error ?? "leave_client_failed",
|
|
10892
|
+
message: body2.message ?? "Client did not leave.",
|
|
10893
|
+
roles: Array.isArray(body2.roles) ? body2.roles : void 0
|
|
10922
10894
|
});
|
|
10923
10895
|
}
|
|
10924
|
-
|
|
10896
|
+
const body = this._parseTextResult(await this.multiplayerTestEnd(value, timeout, instance_id));
|
|
10897
|
+
return this._textResult(body.success === true && body.ended === true ? {
|
|
10898
|
+
success: true,
|
|
10899
|
+
action,
|
|
10900
|
+
message: body.alreadyEnded === true ? "Multiplayer playtest already ended." : body.teardownConfirmed === false ? 'Multiplayer playtest end requested; teardown still in progress. Use multiplayer_playtest action="status" to confirm.' : "Multiplayer playtest ended.",
|
|
10901
|
+
teardownConfirmed: body.teardownConfirmed === true
|
|
10902
|
+
} : {
|
|
10903
|
+
success: false,
|
|
10925
10904
|
action,
|
|
10926
|
-
|
|
10905
|
+
error: body.error ?? "end_failed",
|
|
10906
|
+
message: body.message ?? "Multiplayer playtest did not end.",
|
|
10907
|
+
roles: Array.isArray(body.roles) ? body.roles : void 0,
|
|
10908
|
+
editDone: body.editDone === false ? false : void 0
|
|
10927
10909
|
});
|
|
10928
10910
|
}
|
|
10929
|
-
async multiplayerTestStart(numPlayers, testArgs, timeout, instance_id
|
|
10911
|
+
async multiplayerTestStart(numPlayers, testArgs, timeout, instance_id) {
|
|
10930
10912
|
if (!Number.isInteger(numPlayers) || numPlayers < 1 || numPlayers > 8) {
|
|
10931
10913
|
throw new Error("numPlayers must be an integer from 1 to 8");
|
|
10932
10914
|
}
|
|
10933
10915
|
const editTarget = this._resolveSingleTarget("edit", instance_id);
|
|
10934
|
-
if (force !== true) {
|
|
10935
|
-
return this._textResult({
|
|
10936
|
-
success: false,
|
|
10937
|
-
error: "multiplayer_force_required",
|
|
10938
|
-
message: MULTIPLAYER_FORCE_REQUIRED_MESSAGE,
|
|
10939
|
-
requiresForce: true,
|
|
10940
|
-
manualCleanupRequired: true
|
|
10941
|
-
});
|
|
10942
|
-
}
|
|
10943
10916
|
const existingRuntime = this._runtimeTargetsForEquivalentInstances(editTarget.instanceId);
|
|
10944
10917
|
if (existingRuntime.length > 0) {
|
|
10945
10918
|
const roles = this._rolesForEquivalentInstances(editTarget.instanceId);
|
|
10946
10919
|
return this._textResult({
|
|
10947
10920
|
success: false,
|
|
10948
10921
|
error: "Multiplayer playtest already running.",
|
|
10949
|
-
message: "A Studio runtime is already connected for this place.
|
|
10922
|
+
message: "A Studio runtime is already connected for this place. End the existing playtest before starting another multiplayer playtest.",
|
|
10950
10923
|
ready: true,
|
|
10951
10924
|
timedOut: false,
|
|
10952
10925
|
roles,
|
|
10953
|
-
runtimeRoles: existingRuntime.map((target) => target.role)
|
|
10954
|
-
manualCleanupRequired: true
|
|
10926
|
+
runtimeRoles: existingRuntime.map((target) => target.role)
|
|
10955
10927
|
});
|
|
10956
10928
|
}
|
|
10957
10929
|
const startedAt = Date.now();
|
|
@@ -10977,8 +10949,7 @@ ${code}`
|
|
|
10977
10949
|
roles: wait.roles,
|
|
10978
10950
|
state,
|
|
10979
10951
|
error: success ? void 0 : wait.error ?? "multiplayer_start_not_detected",
|
|
10980
|
-
message: success ? "Multiplayer Studio test started and runtime peers detected." : "Multiplayer Studio test start was requested, but MCP did not detect the required server/client peers before timeout.
|
|
10981
|
-
manualCleanupRequired: success || response.success === true ? true : void 0,
|
|
10952
|
+
message: success ? "Multiplayer Studio test started and runtime peers detected." : "Multiplayer Studio test start was requested, but MCP did not detect the required server/client peers before timeout.",
|
|
10982
10953
|
startedAt
|
|
10983
10954
|
})
|
|
10984
10955
|
}]
|
|
@@ -11040,10 +11011,39 @@ ${code}`
|
|
|
11040
11011
|
};
|
|
11041
11012
|
}
|
|
11042
11013
|
async multiplayerTestEnd(value, timeout, instance_id) {
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11014
|
+
let serverTarget;
|
|
11015
|
+
try {
|
|
11016
|
+
serverTarget = this._resolveSingleTarget("server", instance_id);
|
|
11017
|
+
} catch (err2) {
|
|
11018
|
+
const instanceId = this._resolveInstanceIdOnly(instance_id);
|
|
11019
|
+
const hasRuntime = this._rolesForInstance(instanceId).some((role) => role === "server" || /^client-\d+$/.test(role));
|
|
11020
|
+
if (!hasRuntime) {
|
|
11021
|
+
return this._textResult({
|
|
11022
|
+
success: true,
|
|
11023
|
+
ended: true,
|
|
11024
|
+
alreadyEnded: true,
|
|
11025
|
+
teardownConfirmed: true,
|
|
11026
|
+
message: "No active multiplayer test to end (already ended)."
|
|
11027
|
+
});
|
|
11028
|
+
}
|
|
11029
|
+
throw err2;
|
|
11030
|
+
}
|
|
11031
|
+
const response = await this.client.request("/api/multiplayer-test-end", { value: value ?? "ended_by_mcp" }, serverTarget.instanceId, serverTarget.role);
|
|
11032
|
+
if (response?.error) {
|
|
11033
|
+
return this._textResult(response);
|
|
11034
|
+
}
|
|
11035
|
+
const editDone = await this._waitForMultiplayerEditDone(serverTarget.instanceId, timeout ?? 30);
|
|
11036
|
+
const wait = await this._waitForRuntimeRoles(serverTarget.instanceId, { noRuntime: true }, timeout ?? 30);
|
|
11037
|
+
const state = await this._buildMultiplayerState(serverTarget.instanceId);
|
|
11038
|
+
return this._textResult({
|
|
11039
|
+
...response,
|
|
11040
|
+
ended: response.success === true,
|
|
11041
|
+
teardownConfirmed: wait.ok,
|
|
11042
|
+
editDone,
|
|
11043
|
+
timedOut: wait.timedOut,
|
|
11044
|
+
roles: wait.roles,
|
|
11045
|
+
state
|
|
11046
|
+
});
|
|
11047
11047
|
}
|
|
11048
11048
|
async getConnectedInstances() {
|
|
11049
11049
|
const instances = this.bridge.getPublicInstances();
|
|
@@ -14107,7 +14107,7 @@ var init_definitions = __esm({
|
|
|
14107
14107
|
{
|
|
14108
14108
|
name: "multiplayer_playtest",
|
|
14109
14109
|
category: "write",
|
|
14110
|
-
description: 'Start or
|
|
14110
|
+
description: 'Start, inspect, add players to, remove a client from, or end a StudioTestService multiplayer playtest. Use action="start" with numPlayers, action="status", action="add_players" with numPlayers, action="leave_client" with target="client-N", or action="end". Returns brief lifecycle status only; read script output with get_runtime_logs.',
|
|
14111
14111
|
inputSchema: {
|
|
14112
14112
|
type: "object",
|
|
14113
14113
|
properties: {
|
|
@@ -14128,15 +14128,11 @@ var init_definitions = __esm({
|
|
|
14128
14128
|
description: 'For action="start": JSON-compatible table passed to StudioTestService:GetTestArgs() on server and clients.'
|
|
14129
14129
|
},
|
|
14130
14130
|
value: {
|
|
14131
|
-
description: '
|
|
14132
|
-
},
|
|
14133
|
-
force: {
|
|
14134
|
-
type: "boolean",
|
|
14135
|
-
description: 'Required for action="start". Pass true only if you understand StudioTestService:EndTest is broken in this flow and you will manually close the multiplayer test windows.'
|
|
14131
|
+
description: 'For action="end": JSON-compatible value returned to the edit-side ExecuteMultiplayerTestAsync call.'
|
|
14136
14132
|
},
|
|
14137
14133
|
timeout: {
|
|
14138
14134
|
type: "number",
|
|
14139
|
-
description: "Max seconds to wait for
|
|
14135
|
+
description: "Max seconds to wait for action completion. Defaults to 30."
|
|
14140
14136
|
},
|
|
14141
14137
|
instance_id: {
|
|
14142
14138
|
type: "string",
|
|
@@ -15479,7 +15475,7 @@ part(0,2,0,2,1,1,"b")`,
|
|
|
15479
15475
|
{
|
|
15480
15476
|
name: "multiplayer_test_start",
|
|
15481
15477
|
category: "write",
|
|
15482
|
-
description: 'Deprecated. Use multiplayer_playtest with action="start" instead. Starts a StudioTestService multiplayer test
|
|
15478
|
+
description: 'Deprecated. Use multiplayer_playtest with action="start" instead. Starts a StudioTestService multiplayer test.',
|
|
15483
15479
|
inputSchema: {
|
|
15484
15480
|
type: "object",
|
|
15485
15481
|
properties: {
|
|
@@ -15490,10 +15486,6 @@ part(0,2,0,2,1,1,"b")`,
|
|
|
15490
15486
|
testArgs: {
|
|
15491
15487
|
description: "JSON-compatible table passed to StudioTestService:GetTestArgs() on server and clients."
|
|
15492
15488
|
},
|
|
15493
|
-
force: {
|
|
15494
|
-
type: "boolean",
|
|
15495
|
-
description: "Required. Pass true only if you understand StudioTestService:EndTest is broken in this flow and you will manually close the multiplayer test windows."
|
|
15496
|
-
},
|
|
15497
15489
|
timeout: {
|
|
15498
15490
|
type: "number",
|
|
15499
15491
|
description: "Max seconds to wait for server + clients to register (default 30)."
|
|
@@ -15503,7 +15495,7 @@ part(0,2,0,2,1,1,"b")`,
|
|
|
15503
15495
|
description: "Which connected Studio place to target. Required when multiple places are connected; omit when one. Use get_connected_instances to list available IDs."
|
|
15504
15496
|
}
|
|
15505
15497
|
},
|
|
15506
|
-
required: ["numPlayers"
|
|
15498
|
+
required: ["numPlayers"]
|
|
15507
15499
|
}
|
|
15508
15500
|
},
|
|
15509
15501
|
{
|
|
@@ -15568,16 +15560,16 @@ part(0,2,0,2,1,1,"b")`,
|
|
|
15568
15560
|
{
|
|
15569
15561
|
name: "multiplayer_test_end",
|
|
15570
15562
|
category: "write",
|
|
15571
|
-
description:
|
|
15563
|
+
description: 'Deprecated. Use multiplayer_playtest with action="end" instead. Ends a running StudioTestService multiplayer test.',
|
|
15572
15564
|
inputSchema: {
|
|
15573
15565
|
type: "object",
|
|
15574
15566
|
properties: {
|
|
15575
15567
|
value: {
|
|
15576
|
-
description: "
|
|
15568
|
+
description: "JSON-compatible value returned to the edit-side ExecuteMultiplayerTestAsync call."
|
|
15577
15569
|
},
|
|
15578
15570
|
timeout: {
|
|
15579
15571
|
type: "number",
|
|
15580
|
-
description: "
|
|
15572
|
+
description: "Max seconds to wait for runtime peers to disconnect (default 30)."
|
|
15581
15573
|
},
|
|
15582
15574
|
instance_id: {
|
|
15583
15575
|
type: "string",
|
package/package.json
CHANGED
|
@@ -42,19 +42,19 @@ Complete your AI assistant integration with this easy-to-install Studio plugin.
|
|
|
42
42
|
|
|
43
43
|
## Setup & Configuration
|
|
44
44
|
|
|
45
|
-
###
|
|
46
|
-
**Game Settings** > **Security** > **"Allow HTTP Requests"**
|
|
45
|
+
### Optional: Allow third-party Creator Store assets
|
|
47
46
|
|
|
48
|
-
To preview or insert public Creator Store assets that you do not own,
|
|
49
|
-
|
|
47
|
+
To preview or insert public Creator Store assets that you do not own, enable
|
|
48
|
+
**"Allow Loading Third Party Assets"** under
|
|
49
|
+
**Game Settings** > **Security**.
|
|
50
50
|
Roblox disables this setting by default.
|
|
51
51
|
|
|
52
|
-
###
|
|
52
|
+
### 1. Activate the Plugin
|
|
53
53
|
**Plugins toolbar** > Click **"MCP Server"** button
|
|
54
54
|
- **Green status** = Connected and ready
|
|
55
55
|
- **Red status** = Disconnected (normal until MCP server runs)
|
|
56
56
|
|
|
57
|
-
###
|
|
57
|
+
### 2. Install MCP Server
|
|
58
58
|
Choose your AI assistant:
|
|
59
59
|
|
|
60
60
|
**For Claude Code:**
|
|
@@ -116,10 +116,6 @@ If you encounter issues, you may need to run it through `cmd`. Update your confi
|
|
|
116
116
|
- Restart Roblox Studio completely
|
|
117
117
|
- Check Output window for error messages
|
|
118
118
|
|
|
119
|
-
### "HTTP 403 Forbidden" Errors
|
|
120
|
-
- Enable "Allow HTTP Requests" in Game Settings > Security
|
|
121
|
-
- Verify MCP server is running (status should show connected)
|
|
122
|
-
|
|
123
119
|
### Plugin Shows "Disconnected"
|
|
124
120
|
- **Normal behavior** when MCP server isn't running
|
|
125
121
|
- Click "MCP Server" button to activate
|
|
@@ -132,10 +128,18 @@ If you encounter issues, you may need to run it through `cmd`. Update your confi
|
|
|
132
128
|
|
|
133
129
|
## Security & Privacy
|
|
134
130
|
|
|
135
|
-
- **Local
|
|
136
|
-
|
|
137
|
-
- **
|
|
138
|
-
|
|
131
|
+
- **Local bridge by default**: The plugin connects to `http://localhost:58741`
|
|
132
|
+
unless you explicitly configure another server URL.
|
|
133
|
+
- **Explicit tool access**: The full plugin can modify a place when a write tool
|
|
134
|
+
is called. Install the Inspector edition when you need read-only access.
|
|
135
|
+
- **Provider boundary**: Tool results pass through your configured MCP client.
|
|
136
|
+
Your AI provider's data-handling policy applies to content sent by that
|
|
137
|
+
client.
|
|
138
|
+
|
|
139
|
+
See the repository's
|
|
140
|
+
[configuration guide](../docs/configuration.md) for HTTP bridge authentication
|
|
141
|
+
and network settings. Report suspected vulnerabilities through the
|
|
142
|
+
[security policy](../SECURITY.md), not a public issue.
|
|
139
143
|
|
|
140
144
|
## Advanced Usage
|
|
141
145
|
|
|
@@ -1550,9 +1550,9 @@ local function computeBridgeStamp()
|
|
|
1550
1550
|
for i = 1, #combined do
|
|
1551
1551
|
h = (h * 33 + (string.byte(combined, i))) % 2147483647
|
|
1552
1552
|
end
|
|
1553
|
-
-- "2.23.
|
|
1553
|
+
-- "2.23.1" is replaced with the package version at package time
|
|
1554
1554
|
-- (scripts/build-plugin.mjs injectVersion), so a release bump also restamps.
|
|
1555
|
-
return `{tostring(h)}-2.23.
|
|
1555
|
+
return `{tostring(h)}-2.23.1`
|
|
1556
1556
|
end
|
|
1557
1557
|
local BRIDGE_STAMP = computeBridgeStamp()
|
|
1558
1558
|
local function setSource(scriptInst, source)
|
|
@@ -10036,13 +10036,25 @@ local function multiplayerTestLeaveClient(_requestData)
|
|
|
10036
10036
|
localPlayer = localPlayer,
|
|
10037
10037
|
}
|
|
10038
10038
|
end
|
|
10039
|
-
local function multiplayerTestEnd(
|
|
10039
|
+
local function multiplayerTestEnd(requestData)
|
|
10040
|
+
if not RunService:IsRunning() or not RunService:IsServer() then
|
|
10041
|
+
return {
|
|
10042
|
+
error = "multiplayer_test_end must be called on the running server peer. Route with target=server.",
|
|
10043
|
+
}
|
|
10044
|
+
end
|
|
10045
|
+
local value = if requestData.value ~= nil then requestData.value else "ended_by_mcp"
|
|
10046
|
+
local ok, result = pcall(function()
|
|
10047
|
+
return StudioTestService:EndTest(value)
|
|
10048
|
+
end)
|
|
10049
|
+
if not ok then
|
|
10050
|
+
return {
|
|
10051
|
+
error = tostring(result),
|
|
10052
|
+
}
|
|
10053
|
+
end
|
|
10040
10054
|
return {
|
|
10041
|
-
success =
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
reason = "StudioTestService:EndTest does not reliably end StudioTestService multiplayer sessions from MCP right now.",
|
|
10045
|
-
manualCleanupRequired = true,
|
|
10055
|
+
success = true,
|
|
10056
|
+
message = "Multiplayer Studio test end requested.",
|
|
10057
|
+
value = value,
|
|
10046
10058
|
}
|
|
10047
10059
|
end
|
|
10048
10060
|
return {
|
|
@@ -11080,7 +11092,7 @@ return {
|
|
|
11080
11092
|
<Properties>
|
|
11081
11093
|
<string name="Name">State</string>
|
|
11082
11094
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
11083
|
-
local CURRENT_VERSION = "2.23.
|
|
11095
|
+
local CURRENT_VERSION = "2.23.1"
|
|
11084
11096
|
local PLUGIN_VARIANT = "inspector"
|
|
11085
11097
|
local BASE_PORT = 58741
|
|
11086
11098
|
local function createConnection(port)
|
|
@@ -1550,9 +1550,9 @@ local function computeBridgeStamp()
|
|
|
1550
1550
|
for i = 1, #combined do
|
|
1551
1551
|
h = (h * 33 + (string.byte(combined, i))) % 2147483647
|
|
1552
1552
|
end
|
|
1553
|
-
-- "2.23.
|
|
1553
|
+
-- "2.23.1" is replaced with the package version at package time
|
|
1554
1554
|
-- (scripts/build-plugin.mjs injectVersion), so a release bump also restamps.
|
|
1555
|
-
return `{tostring(h)}-2.23.
|
|
1555
|
+
return `{tostring(h)}-2.23.1`
|
|
1556
1556
|
end
|
|
1557
1557
|
local BRIDGE_STAMP = computeBridgeStamp()
|
|
1558
1558
|
local function setSource(scriptInst, source)
|
|
@@ -10036,13 +10036,25 @@ local function multiplayerTestLeaveClient(_requestData)
|
|
|
10036
10036
|
localPlayer = localPlayer,
|
|
10037
10037
|
}
|
|
10038
10038
|
end
|
|
10039
|
-
local function multiplayerTestEnd(
|
|
10039
|
+
local function multiplayerTestEnd(requestData)
|
|
10040
|
+
if not RunService:IsRunning() or not RunService:IsServer() then
|
|
10041
|
+
return {
|
|
10042
|
+
error = "multiplayer_test_end must be called on the running server peer. Route with target=server.",
|
|
10043
|
+
}
|
|
10044
|
+
end
|
|
10045
|
+
local value = if requestData.value ~= nil then requestData.value else "ended_by_mcp"
|
|
10046
|
+
local ok, result = pcall(function()
|
|
10047
|
+
return StudioTestService:EndTest(value)
|
|
10048
|
+
end)
|
|
10049
|
+
if not ok then
|
|
10050
|
+
return {
|
|
10051
|
+
error = tostring(result),
|
|
10052
|
+
}
|
|
10053
|
+
end
|
|
10040
10054
|
return {
|
|
10041
|
-
success =
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
reason = "StudioTestService:EndTest does not reliably end StudioTestService multiplayer sessions from MCP right now.",
|
|
10045
|
-
manualCleanupRequired = true,
|
|
10055
|
+
success = true,
|
|
10056
|
+
message = "Multiplayer Studio test end requested.",
|
|
10057
|
+
value = value,
|
|
10046
10058
|
}
|
|
10047
10059
|
end
|
|
10048
10060
|
return {
|
|
@@ -11080,7 +11092,7 @@ return {
|
|
|
11080
11092
|
<Properties>
|
|
11081
11093
|
<string name="Name">State</string>
|
|
11082
11094
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
11083
|
-
local CURRENT_VERSION = "2.23.
|
|
11095
|
+
local CURRENT_VERSION = "2.23.1"
|
|
11084
11096
|
local PLUGIN_VARIANT = "main"
|
|
11085
11097
|
local BASE_PORT = 58741
|
|
11086
11098
|
local function createConnection(port)
|
|
@@ -322,13 +322,20 @@ function multiplayerTestLeaveClient(_requestData: Record<string, unknown>) {
|
|
|
322
322
|
};
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
-
function multiplayerTestEnd(
|
|
325
|
+
function multiplayerTestEnd(requestData: Record<string, unknown>) {
|
|
326
|
+
if (!RunService.IsRunning() || !RunService.IsServer()) {
|
|
327
|
+
return { error: "multiplayer_test_end must be called on the running server peer. Route with target=server." };
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const value = requestData.value !== undefined ? requestData.value : "ended_by_mcp";
|
|
331
|
+
const [ok, result] = pcall(() => StudioTestService.EndTest(value));
|
|
332
|
+
if (!ok) {
|
|
333
|
+
return { error: tostring(result) };
|
|
334
|
+
}
|
|
326
335
|
return {
|
|
327
|
-
success:
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
reason: "StudioTestService:EndTest does not reliably end StudioTestService multiplayer sessions from MCP right now.",
|
|
331
|
-
manualCleanupRequired: true,
|
|
336
|
+
success: true,
|
|
337
|
+
message: "Multiplayer Studio test end requested.",
|
|
338
|
+
value,
|
|
332
339
|
};
|
|
333
340
|
}
|
|
334
341
|
|