rbxstudio-mcp 1.12.0 → 1.12.2

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
@@ -27,7 +27,7 @@ class RobloxStudioMCPServer {
27
27
  constructor() {
28
28
  this.server = new Server({
29
29
  name: 'rbxstudio-mcp',
30
- version: '1.12.0',
30
+ version: '1.12.2',
31
31
  }, {
32
32
  capabilities: {
33
33
  tools: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rbxstudio-mcp",
3
- "version": "1.12.0",
3
+ "version": "1.12.2",
4
4
  "description": "MCP Server for Roblox Studio Integration - Access Studio data, scripts, and objects through AI tools",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -22,6 +22,38 @@ local actionHistory = {} -- Stack of actions that can be undone
22
22
  local redoHistory = {} -- Stack of actions that can be redone
23
23
  local MAX_ACTION_HISTORY = 100
24
24
 
25
+ -- Helper to serialize values nicely for logging
26
+ local function serializeValue(value)
27
+ local t = typeof(value)
28
+ if t == "Vector3" then
29
+ return string.format("Vector3(%.2f, %.2f, %.2f)", value.X, value.Y, value.Z)
30
+ elseif t == "Vector2" then
31
+ return string.format("Vector2(%.2f, %.2f)", value.X, value.Y)
32
+ elseif t == "Color3" then
33
+ return string.format("Color3(%.2f, %.2f, %.2f)", value.R, value.G, value.B)
34
+ elseif t == "BrickColor" then
35
+ return "BrickColor(" .. value.Name .. ")"
36
+ elseif t == "UDim2" then
37
+ return string.format("UDim2(%.2f, %d, %.2f, %d)", value.X.Scale, value.X.Offset, value.Y.Scale, value.Y.Offset)
38
+ elseif t == "UDim" then
39
+ return string.format("UDim(%.2f, %d)", value.Scale, value.Offset)
40
+ elseif t == "CFrame" then
41
+ return string.format("CFrame(%.1f, %.1f, %.1f)", value.X, value.Y, value.Z)
42
+ elseif t == "table" then
43
+ if #value > 0 then
44
+ local parts = {}
45
+ for i, v in ipairs(value) do
46
+ if i > 3 then table.insert(parts, "...") break end
47
+ table.insert(parts, serializeValue(v))
48
+ end
49
+ return "{" .. table.concat(parts, ", ") .. "}"
50
+ end
51
+ return "{...}"
52
+ else
53
+ return tostring(value)
54
+ end
55
+ end
56
+
25
57
  -- Helper to log an action for undo tracking
26
58
  local function logAction(actionType, target, summary, details)
27
59
  -- Clear redo history when a new action is performed
@@ -79,7 +111,7 @@ local screenGui = plugin:CreateDockWidgetPluginGuiAsync(
79
111
  "MCPServerInterface",
80
112
  DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, false, false, 400, 500, 350, 450)
81
113
  )
82
- screenGui.Title = "MCP Server v1.12.0"
114
+ screenGui.Title = "MCP Server v1.12.2"
83
115
 
84
116
  local mainFrame = Instance.new("Frame")
85
117
  mainFrame.Size = UDim2.new(1, 0, 1, 0)
@@ -132,7 +164,7 @@ local versionLabel = Instance.new("TextLabel")
132
164
  versionLabel.Size = UDim2.new(1, 0, 0, 16)
133
165
  versionLabel.Position = UDim2.new(0, 0, 0, 32)
134
166
  versionLabel.BackgroundTransparency = 1
135
- versionLabel.Text = "AI Integration • v1.12.0"
167
+ versionLabel.Text = "AI Integration • v1.12.2"
136
168
  versionLabel.TextColor3 = Color3.fromRGB(191, 219, 254)
137
169
  versionLabel.TextScaled = false
138
170
  versionLabel.TextSize = 12
@@ -1490,7 +1522,7 @@ handlers.setProperty = function(requestData)
1490
1522
 
1491
1523
  if success and result ~= false then
1492
1524
  -- Log for undo tracking
1493
- logAction("set_property", instancePath, propertyName .. " = " .. tostring(propertyValue), {
1525
+ logAction("set_property", instancePath, propertyName .. " = " .. serializeValue(propertyValue), {
1494
1526
  propertyName = propertyName,
1495
1527
  newValue = propertyValue
1496
1528
  })
@@ -2805,83 +2837,25 @@ local function countOccurrences(source, searchStr)
2805
2837
  return count
2806
2838
  end
2807
2839
 
2808
- -- Helper: Simple Lua syntax validation (checks for balanced blocks)
2840
+ -- Helper: Real Lua syntax validation using loadstring (same as validate_script)
2809
2841
  local function validateLuaSyntax(source)
2810
- local errors = {}
2811
-
2812
- -- Check for balanced keywords
2813
- local blockStarters = { "function", "if", "for", "while", "do", "repeat" }
2814
- local openBlocks = 0
2815
- local repeatBlocks = 0
2816
-
2817
- -- Simple pattern-based checking for common errors
2818
- for line in string.gmatch(source .. "\n", "([^\n]*)\n") do
2819
- -- Count block starters
2820
- if string.match(line, "^%s*function%s") or string.match(line, "=%s*function%s*%(") or string.match(line, "^%s*local%s+function%s") then
2821
- openBlocks = openBlocks + 1
2822
- end
2823
- if string.match(line, "^%s*if%s") and not string.match(line, "%sthen%s+.+%send%s*$") then
2824
- openBlocks = openBlocks + 1
2825
- end
2826
- if string.match(line, "^%s*for%s") and string.match(line, "%sdo%s*$") then
2827
- openBlocks = openBlocks + 1
2828
- end
2829
- if string.match(line, "^%s*while%s") and string.match(line, "%sdo%s*$") then
2830
- openBlocks = openBlocks + 1
2831
- end
2832
- if string.match(line, "^%s*repeat%s*$") then
2833
- repeatBlocks = repeatBlocks + 1
2842
+ local success, result = pcall(function()
2843
+ local fn, err = loadstring(source)
2844
+ if err then
2845
+ return { valid = false, error = err }
2834
2846
  end
2847
+ return { valid = true }
2848
+ end)
2835
2849
 
2836
- -- Count block enders
2837
- if string.match(line, "^%s*end%s*$") or string.match(line, "^%s*end[%)%],;%s]") or string.match(line, "%send%s*$") then
2838
- if not string.match(line, "^%s*%-%-") then -- Not a comment
2839
- openBlocks = openBlocks - 1
2840
- end
2841
- end
2842
- if string.match(line, "^%s*until%s") then
2843
- repeatBlocks = repeatBlocks - 1
2844
- end
2850
+ if not success then
2851
+ return false, { "Failed to validate: " .. tostring(result) }
2845
2852
  end
2846
2853
 
2847
- if openBlocks > 0 then
2848
- table.insert(errors, "Missing " .. openBlocks .. " 'end' statement(s) - check your function/if/for/while blocks")
2849
- elseif openBlocks < 0 then
2850
- table.insert(errors, "Extra " .. math.abs(openBlocks) .. " 'end' statement(s) - you have more 'end' keywords than block openers")
2851
- end
2852
-
2853
- if repeatBlocks > 0 then
2854
- table.insert(errors, "Missing " .. repeatBlocks .. " 'until' statement(s) for repeat blocks")
2855
- elseif repeatBlocks < 0 then
2856
- table.insert(errors, "Extra " .. math.abs(repeatBlocks) .. " 'until' statement(s)")
2857
- end
2858
-
2859
- -- Check for unclosed strings (simple check)
2860
- local inString = false
2861
- local stringChar = nil
2862
- local lineNum = 0
2863
- for line in string.gmatch(source .. "\n", "([^\n]*)\n") do
2864
- lineNum = lineNum + 1
2865
- -- Skip long strings and comments for now
2866
- if not string.match(line, "%[%[") and not string.match(line, "%-%-") then
2867
- for i = 1, #line do
2868
- local char = string.sub(line, i, i)
2869
- if not inString then
2870
- if char == '"' or char == "'" then
2871
- inString = true
2872
- stringChar = char
2873
- end
2874
- else
2875
- if char == stringChar and string.sub(line, i-1, i-1) ~= "\\" then
2876
- inString = false
2877
- stringChar = nil
2878
- end
2879
- end
2880
- end
2881
- end
2854
+ if result.error then
2855
+ return false, { result.error }
2882
2856
  end
2883
2857
 
2884
- return #errors == 0, errors
2858
+ return true, {}
2885
2859
  end
2886
2860
 
2887
2861
  -- edit_script: String-based editing like Claude Code's Edit tool