@chrrxs/robloxstudio-mcp 3.0.0 → 3.0.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.
Files changed (48) hide show
  1. package/dist/index.js +217 -51
  2. package/package.json +2 -2
  3. package/studio-plugin/MCPPlugin.rbxmx +332 -40
  4. package/studio-plugin/.Carbon.rbxm.lock +0 -0
  5. package/studio-plugin/Carbon.rbxm +0 -0
  6. package/studio-plugin/INSTALLATION.md +0 -170
  7. package/studio-plugin/MCPInspectorPlugin.rbxmx +0 -169759
  8. package/studio-plugin/default.project.json +0 -19
  9. package/studio-plugin/dev.project.json +0 -23
  10. package/studio-plugin/include/LibMP.lua +0 -156378
  11. package/studio-plugin/inspector-icon.png +0 -0
  12. package/studio-plugin/package-lock.json +0 -706
  13. package/studio-plugin/package.json +0 -19
  14. package/studio-plugin/plugin.json +0 -10
  15. package/studio-plugin/src/modules/AssetSanitizationPolicy.ts +0 -127
  16. package/studio-plugin/src/modules/ClientBroker.ts +0 -450
  17. package/studio-plugin/src/modules/Communication.ts +0 -601
  18. package/studio-plugin/src/modules/EvalBridges.ts +0 -255
  19. package/studio-plugin/src/modules/HttpDiagnostics.ts +0 -50
  20. package/studio-plugin/src/modules/LuauExec.ts +0 -403
  21. package/studio-plugin/src/modules/Recording.ts +0 -28
  22. package/studio-plugin/src/modules/RenderMonitor.ts +0 -60
  23. package/studio-plugin/src/modules/RuntimeLogBuffer.ts +0 -210
  24. package/studio-plugin/src/modules/ServerUrlSettings.ts +0 -117
  25. package/studio-plugin/src/modules/State.ts +0 -39
  26. package/studio-plugin/src/modules/StopPlayMonitor.ts +0 -267
  27. package/studio-plugin/src/modules/UI.ts +0 -597
  28. package/studio-plugin/src/modules/Utils.ts +0 -527
  29. package/studio-plugin/src/modules/handlers/AssetHandlers.ts +0 -391
  30. package/studio-plugin/src/modules/handlers/BreakpointHandlers.ts +0 -460
  31. package/studio-plugin/src/modules/handlers/CaptureHandlers.ts +0 -170
  32. package/studio-plugin/src/modules/handlers/EvalRuntimeHandlers.ts +0 -149
  33. package/studio-plugin/src/modules/handlers/GenerateModelHandlers.ts +0 -168
  34. package/studio-plugin/src/modules/handlers/InputHandlers.ts +0 -163
  35. package/studio-plugin/src/modules/handlers/LogHandlers.ts +0 -14
  36. package/studio-plugin/src/modules/handlers/MemoryHandlers.ts +0 -44
  37. package/studio-plugin/src/modules/handlers/MetadataHandlers.ts +0 -96
  38. package/studio-plugin/src/modules/handlers/MicroProfilerHandlers.ts +0 -1263
  39. package/studio-plugin/src/modules/handlers/PropertyHandlers.ts +0 -62
  40. package/studio-plugin/src/modules/handlers/QueryHandlers.ts +0 -716
  41. package/studio-plugin/src/modules/handlers/SceneAnalysisHandlers.ts +0 -216
  42. package/studio-plugin/src/modules/handlers/ScriptHandlers.ts +0 -531
  43. package/studio-plugin/src/modules/handlers/ScriptProfilerHandlers.ts +0 -386
  44. package/studio-plugin/src/modules/handlers/SerializationHandlers.ts +0 -172
  45. package/studio-plugin/src/modules/handlers/TestHandlers.ts +0 -350
  46. package/studio-plugin/src/server/index.server.ts +0 -135
  47. package/studio-plugin/src/types/index.d.ts +0 -57
  48. package/studio-plugin/tsconfig.json +0 -20
@@ -1,350 +0,0 @@
1
- import { HttpService, Players, RunService } from "@rbxts/services";
2
- import StopPlayMonitor from "../StopPlayMonitor";
3
-
4
- interface StudioTestServiceMultiplayer extends StudioTestService {
5
- ExecuteMultiplayerTestAsync(numPlayers: number, testArgs: unknown): unknown;
6
- AddPlayers(numPlayers: number): void;
7
- CanLeaveTest(): boolean;
8
- LeaveTest(): void;
9
- EditModeActive: boolean;
10
- }
11
-
12
- const StudioTestService = game.GetService("StudioTestService") as StudioTestServiceMultiplayer;
13
-
14
- let testRunning = false;
15
-
16
- type MultiplayerPhase = "idle" | "starting" | "running" | "completed" | "failed";
17
-
18
- interface MultiplayerSessionState {
19
- phase: MultiplayerPhase;
20
- testId?: string;
21
- numPlayers?: number;
22
- testArgs?: unknown;
23
- startedAt?: number;
24
- completedAt?: number;
25
- ok?: boolean;
26
- result?: unknown;
27
- error?: string;
28
- }
29
-
30
- let multiplayerState: MultiplayerSessionState = { phase: "idle" };
31
-
32
- function detectPeerRole(): string {
33
- if (!RunService.IsRunning()) return "edit";
34
- if (RunService.IsServer()) return "server";
35
- return "client";
36
- }
37
-
38
- function getPlayersSnapshot() {
39
- const players = Players.GetPlayers().map((player) => ({
40
- name: player.Name,
41
- userId: player.UserId,
42
- displayName: player.DisplayName,
43
- }));
44
- players.sort((a, b) => a.name < b.name);
45
- return players;
46
- }
47
-
48
- function cloneMultiplayerState(): MultiplayerSessionState {
49
- return {
50
- phase: multiplayerState.phase,
51
- testId: multiplayerState.testId,
52
- numPlayers: multiplayerState.numPlayers,
53
- testArgs: multiplayerState.testArgs,
54
- startedAt: multiplayerState.startedAt,
55
- completedAt: multiplayerState.completedAt,
56
- ok: multiplayerState.ok,
57
- result: multiplayerState.result,
58
- error: multiplayerState.error,
59
- };
60
- }
61
-
62
- function normalizeNumPlayers(value: unknown): number | undefined {
63
- if (!typeIs(value, "number")) return undefined;
64
- const n = math.floor(value);
65
- if (n !== value || n < 1 || n > 8) return undefined;
66
- return n;
67
- }
68
-
69
- function startPlaytest(requestData: Record<string, unknown>) {
70
- const mode = requestData.mode as string | undefined;
71
- const numPlayers = requestData.numPlayers as number | undefined;
72
-
73
- if (mode !== "play" && mode !== "run") {
74
- return { error: 'mode must be "play" or "run"' };
75
- }
76
-
77
- if (numPlayers !== undefined) {
78
- return { error: "start_playtest is single-player only. Use multiplayer_test_start for multi-client StudioTestService sessions." };
79
- }
80
-
81
- // Self-heal: if testRunning is stuck true but Studio reports no active
82
- // playtest, the previous start_playtest's task.spawn was orphaned
83
- // (plugin reload mid-test, Studio entered some inconsistent state, etc).
84
- // Reset it so subsequent starts don't hit a false "already running".
85
- if (testRunning && !RunService.IsRunning()) {
86
- testRunning = false;
87
- // Runtime eval bridges are created by the play server/client plugin
88
- // peers and disappear with the play DataModels.
89
- }
90
-
91
- if (testRunning) {
92
- return { error: "A test is already running" };
93
- }
94
-
95
- testRunning = true;
96
-
97
- task.spawn(() => {
98
- const [ok, result] = pcall(() => {
99
- if (mode === "play") {
100
- return StudioTestService.ExecutePlayModeAsync({});
101
- }
102
- return StudioTestService.ExecuteRunModeAsync({});
103
- });
104
-
105
- if (!ok) {
106
- warn(`[robloxstudio-mcp] Playtest ended with error: ${result}`);
107
- }
108
-
109
- testRunning = false;
110
- });
111
-
112
- const response: Record<string, unknown> = {
113
- success: true,
114
- message: `Playtest started in ${mode} mode.`,
115
- };
116
-
117
- return response;
118
- }
119
-
120
- function stopPlaytest(_requestData: Record<string, unknown>) {
121
- // Signal the play-server DM's StopPlayMonitor via plugin:SetSetting.
122
- // The monitor acknowledges with the matching request id only after its
123
- // StudioTestService:EndTest call returns from pcall.
124
- const stopRequest = StopPlayMonitor.requestStop();
125
- if (!stopRequest.ok || stopRequest.requestId === undefined) {
126
- return { error: "Plugin not ready. Try again in a moment." };
127
- }
128
- const consumption = StopPlayMonitor.waitForConsumption(stopRequest.requestId);
129
- if (!consumption.ok) {
130
- // Two distinct failure modes collapse here, distinguished by whether
131
- // THIS edit DM has a playtest tracked:
132
- //
133
- // - testRunning=false: no playtest was running from this edit DM
134
- // (true negative). Return "no active playtest" — fine to retry only
135
- // after actually starting a playtest.
136
- // - testRunning=true: a playtest IS running but the cross-DM signal
137
- // didn't propagate within the consumption timeout (false negative
138
- // from the caller's perspective — playtest may actually have ended).
139
- // Tell the caller it's a timing issue and they can retry.
140
- //
141
- // Either way clean up the pending request so a future playtest's monitor
142
- // doesn't fire EndTest on startup against a stale signal.
143
- StopPlayMonitor.clearPending(stopRequest.requestId);
144
- if (testRunning) {
145
- return {
146
- error:
147
- "Playtest stop signal failed or was not acknowledged. " +
148
- "The playtest may have ended anyway; check get_connected_instances.",
149
- detail: consumption.error,
150
- };
151
- }
152
- if (consumption.consumed) {
153
- return { error: "Playtest stop request reached the play server, but EndTest failed.", detail: consumption.error };
154
- }
155
- return { error: "No active playtest to stop.", detail: consumption.error };
156
- }
157
- StopPlayMonitor.clearPending(stopRequest.requestId);
158
- // Request was consumed (EndTest called). ExecutePlayModeAsync in our
159
- // startPlaytest task.spawn is still unwinding though — testRunning stays
160
- // true until that yield completes and the post-block runs. Wait so
161
- // back-to-back stop -> start sequences don't race against the prior
162
- // teardown and get "A test is already running". 10s covers play-DM
163
- // teardown on heavier places; if it still hasn't cleared we return
164
- // anyway so users aren't stuck — but note that in the response so the
165
- // caller knows a subsequent start may need a moment.
166
- const deadline = tick() + 10;
167
- while (testRunning && tick() < deadline) {
168
- task.wait(0.1);
169
- }
170
- if (testRunning) {
171
- return {
172
- success: true,
173
- message: "Playtest stop signal sent; teardown still in progress.",
174
- };
175
- }
176
- return { success: true, message: "Playtest stopped." };
177
- }
178
-
179
- function multiplayerTestStart(requestData: Record<string, unknown>) {
180
- if (RunService.IsRunning()) {
181
- return { error: "multiplayer_test_start must be called on the edit DataModel. Route with target=edit." };
182
- }
183
-
184
- const numPlayers = normalizeNumPlayers(requestData.numPlayers);
185
- if (numPlayers === undefined) {
186
- return { error: "numPlayers must be an integer from 1 to 8" };
187
- }
188
-
189
- if (multiplayerState.phase === "starting" || multiplayerState.phase === "running") {
190
- return {
191
- error: "A multiplayer Studio test is already running",
192
- state: cloneMultiplayerState(),
193
- };
194
- }
195
-
196
- const testArgs = requestData.testArgs !== undefined ? requestData.testArgs : {};
197
- const testId = HttpService.GenerateGUID(false);
198
-
199
- multiplayerState = {
200
- phase: "starting",
201
- testId,
202
- numPlayers,
203
- testArgs,
204
- startedAt: tick(),
205
- };
206
-
207
- task.spawn(() => {
208
- multiplayerState.phase = "running";
209
- const [ok, result] = pcall(() => {
210
- return StudioTestService.ExecuteMultiplayerTestAsync(numPlayers, testArgs);
211
- });
212
-
213
- multiplayerState.completedAt = tick();
214
- multiplayerState.ok = ok;
215
- if (ok) {
216
- multiplayerState.phase = "completed";
217
- multiplayerState.result = result;
218
- multiplayerState.error = undefined;
219
- } else {
220
- multiplayerState.phase = "failed";
221
- multiplayerState.result = undefined;
222
- multiplayerState.error = tostring(result);
223
- }
224
- });
225
-
226
- const response: Record<string, unknown> = {
227
- success: true,
228
- message: `Multiplayer Studio test starting with ${numPlayers} player(s).`,
229
- testId,
230
- phase: multiplayerState.phase,
231
- numPlayers,
232
- testArgs,
233
- };
234
- return response;
235
- }
236
-
237
- function multiplayerTestState(_requestData: Record<string, unknown>) {
238
- const peer = detectPeerRole();
239
- const response: Record<string, unknown> = {
240
- success: true,
241
- peer,
242
- isRunning: RunService.IsRunning(),
243
- isRunMode: RunService.IsRunMode(),
244
- editModeActive: StudioTestService.EditModeActive,
245
- };
246
-
247
- if (peer === "edit") {
248
- response.session = cloneMultiplayerState();
249
- return response;
250
- }
251
-
252
- const [argsOk, args] = pcall(() => StudioTestService.GetTestArgs());
253
- response.testArgsOk = argsOk;
254
- response.testArgs = argsOk ? args : undefined;
255
- if (!argsOk) response.testArgsError = tostring(args);
256
-
257
- const players = getPlayersSnapshot();
258
- response.players = players;
259
- response.playerCount = players.size();
260
-
261
- if (peer === "client") {
262
- response.localPlayer = Players.LocalPlayer ? Players.LocalPlayer.Name : undefined;
263
- const [canLeaveOk, canLeave] = pcall(() => StudioTestService.CanLeaveTest());
264
- response.canLeaveOk = canLeaveOk;
265
- response.canLeave = canLeaveOk ? canLeave : false;
266
- if (!canLeaveOk) response.canLeaveError = tostring(canLeave);
267
- }
268
-
269
- return response;
270
- }
271
-
272
- function multiplayerTestAddPlayers(requestData: Record<string, unknown>) {
273
- if (!RunService.IsRunning() || !RunService.IsServer()) {
274
- return { error: "multiplayer_test_add_players must be called on the running server peer. Route with target=server." };
275
- }
276
- const numPlayers = normalizeNumPlayers(requestData.numPlayers);
277
- if (numPlayers === undefined) {
278
- return { error: "numPlayers must be an integer from 1 to 8" };
279
- }
280
-
281
- const before = Players.GetPlayers().size();
282
- const [ok, result] = pcall(() => StudioTestService.AddPlayers(numPlayers));
283
- if (!ok) {
284
- return { error: tostring(result) };
285
- }
286
-
287
- const deadline = tick() + ((requestData.timeout as number | undefined) ?? 10);
288
- while (Players.GetPlayers().size() < before + numPlayers && tick() < deadline) {
289
- task.wait(0.1);
290
- }
291
-
292
- const players = getPlayersSnapshot();
293
- return {
294
- success: true,
295
- message: `Requested ${numPlayers} additional player(s).`,
296
- playerCount: players.size(),
297
- players,
298
- };
299
- }
300
-
301
- function multiplayerTestLeaveClient(_requestData: Record<string, unknown>) {
302
- if (!RunService.IsRunning() || RunService.IsServer()) {
303
- return { error: "multiplayer_test_leave_client must be called on a running client peer. Route with target=client-N." };
304
- }
305
-
306
- const [canLeaveOk, canLeave] = pcall(() => StudioTestService.CanLeaveTest());
307
- if (!canLeaveOk) {
308
- return { error: tostring(canLeave), canLeaveOk: false };
309
- }
310
- if (!canLeave) {
311
- return { error: "This client cannot leave the current test session.", canLeaveOk: true, canLeave: false };
312
- }
313
-
314
- const localPlayer = Players.LocalPlayer ? Players.LocalPlayer.Name : undefined;
315
- task.defer(() => {
316
- pcall(() => StudioTestService.LeaveTest());
317
- });
318
- return {
319
- success: true,
320
- message: "Client leave requested.",
321
- localPlayer,
322
- };
323
- }
324
-
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
- }
335
- return {
336
- success: true,
337
- message: "Multiplayer Studio test end requested.",
338
- value,
339
- };
340
- }
341
-
342
- export = {
343
- startPlaytest,
344
- stopPlaytest,
345
- multiplayerTestStart,
346
- multiplayerTestState,
347
- multiplayerTestAddPlayers,
348
- multiplayerTestLeaveClient,
349
- multiplayerTestEnd,
350
- };
@@ -1,135 +0,0 @@
1
- import State from "../modules/State";
2
- import UI from "../modules/UI";
3
- import Communication from "../modules/Communication";
4
- import ClientBroker from "../modules/ClientBroker";
5
- import ServerUrlSettings from "../modules/ServerUrlSettings";
6
- import { cleanupLegacyEditBridges, ensureRuntimeBridgeInstalled } from "../modules/EvalBridges";
7
- import RuntimeLogBuffer from "../modules/RuntimeLogBuffer";
8
- import StopPlayMonitor from "../modules/StopPlayMonitor";
9
- import BreakpointHandlers from "../modules/handlers/BreakpointHandlers";
10
- import * as RenderMonitor from "../modules/RenderMonitor";
11
-
12
- // Track render-loop liveness so input/screenshot tools can report "window
13
- // minimized / not rendering" instead of silently no-op'ing. No-op in the
14
- // server DM (RenderStepped can't connect there).
15
- RenderMonitor.start();
16
-
17
- // Attach the per-peer LogService.MessageOut listener as early as possible so
18
- // boot-time prints from the user's place scripts are captured. Powers the
19
- // get_runtime_logs MCP tool. Idempotent; safe to call before UI.init().
20
- RuntimeLogBuffer.install();
21
-
22
- // Share the plugin reference with the stop-play signaling module so both the
23
- // edit DM (write the flag) and the play-server DM (read+act on the flag) can
24
- // access plugin:SetSetting/GetSetting.
25
- StopPlayMonitor.init(plugin);
26
- BreakpointHandlers.init(plugin);
27
- ServerUrlSettings.init(plugin);
28
-
29
- function applyRememberedServerUrl(): void {
30
- if (ClientBroker.forkRole() === "client") return;
31
-
32
- const rememberedServerUrl = ServerUrlSettings.readServerUrl();
33
- if (rememberedServerUrl === undefined) return;
34
-
35
- const conn = State.getActiveConnection();
36
- conn.serverUrl = rememberedServerUrl;
37
- const port = ServerUrlSettings.extractPort(rememberedServerUrl);
38
- if (port !== undefined) conn.port = port;
39
- ClientBroker.setServerUrl(rememberedServerUrl);
40
- }
41
-
42
- applyRememberedServerUrl();
43
-
44
- UI.init(plugin);
45
- const elements = UI.getElements();
46
-
47
-
48
- const ICON_DISCONNECTED = "rbxassetid://__BUTTON_ICON_DISCONNECTED__";
49
- const ICON_CONNECTING = "rbxassetid://__BUTTON_ICON_CONNECTING__";
50
- const ICON_CONNECTED = "rbxassetid://__BUTTON_ICON_CONNECTED__";
51
- const TOOLBAR_REGISTRATION_DELAY_SECONDS = 1;
52
-
53
- let toolbarButtonRegistered = false;
54
-
55
- function registerToolbarButton() {
56
- if (toolbarButtonRegistered) {
57
- return;
58
- }
59
- toolbarButtonRegistered = true;
60
-
61
- const toolbar = plugin.CreateToolbar("__TOOLBAR_NAME__");
62
- const button = toolbar.CreateButton("__BUTTON_TITLE__", "__BUTTON_TOOLTIP__", ICON_DISCONNECTED);
63
- UI.setToolbarButton(button, { disconnected: ICON_DISCONNECTED, connecting: ICON_CONNECTING, connected: ICON_CONNECTED });
64
-
65
- button.Click.Connect(() => {
66
- elements.screenGui.Enabled = !elements.screenGui.Enabled;
67
- });
68
- }
69
-
70
-
71
- elements.connectButton.Activated.Connect(() => {
72
- const conn = State.getActiveConnection();
73
- if (conn && conn.isActive) {
74
- Communication.deactivatePlugin();
75
- } else {
76
- Communication.activatePlugin();
77
- }
78
- });
79
-
80
-
81
- plugin.Unloading.Connect(() => {
82
- Communication.deactivateAll();
83
- });
84
-
85
-
86
- UI.updateUIState();
87
- Communication.checkForUpdates();
88
- task.delay(TOOLBAR_REGISTRATION_DELAY_SECONDS, registerToolbarButton);
89
-
90
- // Auto-activate per peer. The boshyxd plugin only registers with MCP when the
91
- // user clicks Connect in its UI, but that UI is invisible in play DMs - so
92
- // play peers' plugin instances load without ever registering. Run after a
93
- // short delay so the UI/State have a chance to initialize first.
94
- task.delay(2, () => {
95
- const role = ClientBroker.forkRole();
96
- if (role === "edit") {
97
- cleanupLegacyEditBridges();
98
- } else {
99
- const result = ensureRuntimeBridgeInstalled();
100
- if (!result.installed) {
101
- warn(`[robloxstudio-mcp] Runtime eval bridge install failed: ${result.error}`);
102
- }
103
- }
104
- if (role === "edit" || role === "server") {
105
- pcall(() => {
106
- const conn = State.getActiveConnection();
107
- if (!conn.isActive) {
108
- if (role === "server") {
109
- const inheritedServerUrl = ServerUrlSettings.readServerUrl() ?? ClientBroker.DEFAULT_MCP_URL;
110
- conn.serverUrl = ServerUrlSettings.normalizeServerUrl(inheritedServerUrl);
111
- elements.urlInput.Text = conn.serverUrl;
112
- const port = ServerUrlSettings.extractPort(conn.serverUrl);
113
- if (port !== undefined) conn.port = port;
114
- ClientBroker.setServerUrl(conn.serverUrl);
115
- }
116
- // Defensive default: in invisible play-DM UIs, the input field
117
- // may not be populated by the time we activate.
118
- if (conn.serverUrl === undefined || conn.serverUrl === "") {
119
- conn.serverUrl = ClientBroker.DEFAULT_MCP_URL;
120
- elements.urlInput.Text = conn.serverUrl;
121
- }
122
- Communication.activatePlugin();
123
- }
124
- });
125
- }
126
- if (role === "server") {
127
- ClientBroker.setupServerBroker();
128
- // The play-server DM is the only one where StudioTestService:EndTest is
129
- // legal, so the stop-play monitor lives here. It consumes tokenized
130
- // stop requests from plugin settings and acknowledges EndTest results.
131
- StopPlayMonitor.startMonitor();
132
- } else if (role === "client") {
133
- ClientBroker.setupClientBroker();
134
- }
135
- });
@@ -1,57 +0,0 @@
1
- /// <reference types="@rbxts/types/plugin" />
2
-
3
- export interface Connection {
4
- port: number;
5
- serverUrl: string;
6
- isActive: boolean;
7
- pollInterval: number;
8
- lastPoll: number;
9
- consecutiveFailures: number;
10
- maxFailuresBeforeError: number;
11
- lastSuccessfulConnection: number;
12
- currentRetryDelay: number;
13
- maxRetryDelay: number;
14
- retryBackoffMultiplier: number;
15
- lastHttpOk: boolean;
16
- lastMcpOk: boolean;
17
- mcpWaitStartTime?: number;
18
- isPolling: boolean;
19
- heartbeatConnection?: RBXScriptConnection;
20
- }
21
-
22
- export interface RequestData {
23
- [key: string]: unknown;
24
- }
25
-
26
- export interface RequestPayload {
27
- endpoint: string;
28
- data?: RequestData;
29
- }
30
-
31
- export interface PollResponse {
32
- mcpConnected: boolean;
33
- serverVersion?: string;
34
- pluginVersion?: string;
35
- pluginVariant?: string;
36
- versionMismatch?: boolean;
37
- request?: RequestPayload;
38
- requestId?: string;
39
- // Server signals knownInstance=false when its in-memory instances map
40
- // doesn't contain our pluginSessionId (typically after an MCP process
41
- // restart). The plugin re-issues /ready when it sees this.
42
- knownInstance?: boolean;
43
- }
44
-
45
- export interface ReadyResponse {
46
- success: boolean;
47
- assignedRole?: string;
48
- instanceId?: string;
49
- serverVersion?: string;
50
- versionMismatch?: boolean;
51
- error?: string;
52
- message?: string;
53
- }
54
-
55
- declare global {
56
- function loadstring(code: string): LuaTuple<[(() => unknown) | undefined, string?]>;
57
- }
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowSyntheticDefaultImports": true,
4
- "downlevelIteration": true,
5
- "jsx": "react",
6
- "jsxFactory": "React.createElement",
7
- "jsxFragmentFactory": "React.Fragment",
8
- "module": "commonjs",
9
- "moduleDetection": "force",
10
- "moduleResolution": "node",
11
- "noLib": true,
12
- "resolveJsonModule": true,
13
- "strict": true,
14
- "target": "ESNext",
15
- "typeRoots": ["node_modules/@rbxts"],
16
- "rootDir": "src",
17
- "outDir": "out",
18
- "declaration": false
19
- }
20
- }