Skip to main content

Overview

The execute_lua tool allows you to run arbitrary Luau code directly in Roblox Studio’s plugin context with full API access. This is the most powerful and flexible tool, enabling custom operations, complex calculations, and direct access to Roblox APIs that may not have dedicated MCP tools.

Use Cases

  • Execute custom Roblox API calls not covered by other tools
  • Perform complex calculations or logic in Lua
  • Access advanced Roblox services and APIs
  • Implement custom validation logic
  • Query internal Studio state
  • Run one-off scripts or experiments
  • Prototype new functionality before creating dedicated tools
  • Debug and inspect game state

Parameters

code
string
required
Luau code to execute. Use “return value” to get results back.
args
object
Optional arguments passed as a table to the code (accessible via …)

Response Structure

success
boolean
Whether the code executed successfully
result
any
The value returned by the code (if any)
error
string
Error message if execution failed

Example Response (Success)

{
  "success": true,
  "result": 42
}

Example Response (Error)

{
  "success": false,
  "error": "attempt to index nil with 'Workspace'"
}

Usage Examples

Basic Execution

// Execute simple Lua code
const result = await mcpClient.callTool('execute_lua', {
  code: 'return 2 + 2'
});

console.log('Result:', result.result); // 4

Get Workspace Children Count

const result = await mcpClient.callTool('execute_lua', {
  code: `
    local count = #game.Workspace:GetChildren()
    return count
  `
});

console.log(`Workspace has ${result.result} children`);

Calculate Distance Between Parts

const result = await mcpClient.callTool('execute_lua', {
  code: `
    local part1 = game.Workspace.Part1
    local part2 = game.Workspace.Part2
    local distance = (part1.Position - part2.Position).Magnitude
    return distance
  `
});

console.log(`Distance: ${result.result} studs`);

Check if Instance Exists

const result = await mcpClient.callTool('execute_lua', {
  code: `
    local instance = game.Workspace:FindFirstChild("MyPart")
    return instance ~= nil
  `
});

if (result.result) {
  console.log('MyPart exists');
} else {
  console.log('MyPart not found');
}

Custom Validation

// Validate script syntax
const result = await mcpClient.callTool('execute_lua', {
  code: `
    local script = game.ServerScriptService.MyScript
    local source = script.Source
    local fn, err = loadstring(source)
    if err then
      return {valid = false, error = err}
    else
      return {valid = true}
    end
  `
});

if (result.result.valid) {
  console.log('Script syntax is valid');
} else {
  console.log('Syntax error:', result.result.error);
}

Access Advanced APIs

// Use TweenService to create animation
const result = await mcpClient.callTool('execute_lua', {
  code: `
    local TweenService = game:GetService("TweenService")
    local part = game.Workspace.Part
    
    local goal = {}
    goal.Position = Vector3.new(0, 50, 0)
    
    local tweenInfo = TweenInfo.new(2)
    local tween = TweenService:Create(part, tweenInfo, goal)
    tween:Play()
    
    return "Tween started"
  `
});

console.log(result.result);

Complex Calculations

// Calculate total mass of model
const result = await mcpClient.callTool('execute_lua', {
  code: `
    local model = game.Workspace.ComplexModel
    local totalMass = 0
    
    for _, part in ipairs(model:GetDescendants()) do
      if part:IsA("BasePart") then
        totalMass = totalMass + part.AssemblyMass
      end
    end
    
    return totalMass
  `
});

console.log(`Total mass: ${result.result} units`);

Using Arguments

// Pass arguments to Lua code
const result = await mcpClient.callTool('execute_lua', {
  code: `
    local args = ...
    local partName = args.partName
    local newColor = args.color
    
    local part = game.Workspace:FindFirstChild(partName)
    if part then
      part.BrickColor = BrickColor.new(newColor)
      return "Color changed"
    else
      return "Part not found"
    end
  `,
  args: {
    partName: 'Platform_1',
    color: 'Really red'
  }
});

console.log(result.result);

Query Studio Settings

const result = await mcpClient.callTool('execute_lua', {
  code: `
    local StudioService = game:GetService("StudioService")
    return {
      gridSize = StudioService.GridSize,
      rotateIncrement = StudioService.RotateIncrement
    }
  `
});

console.log('Grid size:', result.result.gridSize);
console.log('Rotate increment:', result.result.rotateIncrement);

Batch Property Get with Lua

// Get multiple properties efficiently in one call
const result = await mcpClient.callTool('execute_lua', {
  code: `
    local parts = {
      game.Workspace.Part1,
      game.Workspace.Part2,
      game.Workspace.Part3
    }
    
    local results = {}
    for _, part in ipairs(parts) do
      table.insert(results, {
        name = part.Name,
        position = {X = part.Position.X, Y = part.Position.Y, Z = part.Position.Z},
        size = {X = part.Size.X, Y = part.Size.Y, Z = part.Size.Z}
      })
    end
    
    return results
  `
});

console.log('Parts data:', result.result);

Check Collision Groups

const result = await mcpClient.callTool('execute_lua', {
  code: `
    local PhysicsService = game:GetService("PhysicsService")
    local groups = PhysicsService:GetRegisteredCollisionGroups()
    
    local groupNames = {}
    for _, group in ipairs(groups) do
      table.insert(groupNames, group.name)
    end
    
    return groupNames
  `
});

console.log('Collision groups:', result.result);

Tips and Best Practices

Use execute_lua for operations that require multiple API calls or complex logic that would be inefficient as separate MCP tool calls.
The code runs in the plugin context with full Studio API access. You have access to all game services and APIs.
Syntax errors or runtime errors will return success = false with an error message. Always check result.success before using result.result.
Return structured data (tables) for complex results. Lua tables are automatically converted to JSON objects.

Lua Context Details

Available Globals

  • game - DataModel root
  • All standard Lua globals (math, string, table, etc.)
  • All Roblox globals (Vector3, CFrame, Color3, etc.)
  • All game services (accessible via game:GetService())

Return Values

  • Use return <value> to send data back
  • Numbers, strings, booleans, tables are supported
  • Roblox datatypes (Vector3, CFrame) are converted to tables
  • Functions and userdata cannot be returned

Accessing Arguments

local args = ...
local myParam = args.paramName

Multi-Line Code

Use template literals in JavaScript:
const code = `
  local part = game.Workspace.Part
  local size = part.Size
  return size.X * size.Y * size.Z
`;

Security and Limitations

What You Can Do

  • Access and modify all game instances
  • Use all Roblox services and APIs
  • Perform calculations and logic
  • Query game state
  • Create/delete objects
  • Modify properties

What You Cannot Do

  • Execute malicious code (runs in sandboxed plugin context)
  • Access file system directly
  • Make HTTP requests (unless HttpService is enabled)
  • Access user’s computer beyond Studio

Error Handling

  • Syntax errors are caught and returned in error field
  • Runtime errors are caught and returned in error field
  • Always check success field before using result

Common Patterns

Safe Execution

const result = await mcpClient.callTool('execute_lua', { code: luaCode });

if (result.success) {
  console.log('Result:', result.result);
} else {
  console.error('Lua error:', result.error);
}

Parameterized Execution

const result = await mcpClient.callTool('execute_lua', {
  code: `
    local args = ...
    -- Use args.param1, args.param2, etc.
    return computeSomething(args)
  `,
  args: { param1: value1, param2: value2 }
});

Return Structured Data

const code = `
  return {
    success = true,
    data = {...},
    message = "Operation complete"
  }
`;

Error Handling in Lua

const code = `
  local success, result = pcall(function()
    -- risky operation
    return someFunction()
  end)
  
  if success then
    return {ok = true, value = result}
  else
    return {ok = false, error = result}
  end
`;

Common Issues

Issue: Syntax error
  • Check Lua syntax carefully (common: missing end, wrong quotes)
  • Use a Lua syntax checker before executing
  • Review error message for line number and details
Issue: Cannot access instance
  • Instance may not exist (use FindFirstChild with nil checks)
  • Path may be incorrect
  • Instance may have been deleted
Issue: Return value is nil
  • Make sure code includes return <value>
  • Check that the value exists before returning
  • Nil values are returned as null in JSON
Issue: Cannot return specific value
  • Some Roblox datatypes can’t be directly returned
  • Convert to tables: {X = vector.X, Y = vector.Y, Z = vector.Z}
  • Functions and userdata cannot be returned

Build docs developers (and LLMs) love