Skip to main content
Glama
EL4CTEO

Roblox Studio MCP

Run Luau in Studio

execute_luau
Destructive

Run Luau code in Roblox Studio's plugin context and capture printed, returned, or thrown output for tasks no dedicated tool exposes.

Instructions

Runs Luau in Studio's plugin context and returns whatever it printed, returned, or threw.

This is the escape hatch. Reach for it only when no dedicated tool fits — create, modify, delete, move, script_edit and find validate their input, type values from the live API dump, and wrap writes in an undo recording. Code run here does none of that, so a typo becomes a runtime error instead of a suggestion, and changes it makes may not be undoable as one step.

Good uses: reading something no tool exposes, a one-off calculation over many instances, or calling an engine API the tools do not cover.

Output printed while it runs is captured and returned, so print is a reasonable way to get values out. return works too, including returning a table — it comes back as a structure, not a summary. There is no timeout for target="studio": an infinite loop will hang Studio until it is force-quit.

Against a running playtest server, Studio disables loadstring, so the code is compiled through a ModuleScript instead and runs at script identity — plugin-only APIs are unavailable there. When that happens it is stated in the result rather than left to be inferred from a failure.

With target="studio", do not use require to read live state out of a running game. This runs in the plugin's own Luau VM with its own module cache, so require here returns a second, freshly-initialised copy of the ModuleScript — its counters and caches read as empty while the real one is running fine, and a zero is indistinguishable from a genuine zero. Read live state off the DataModel instead (instances, attributes, properties), or have the game print it and read that with console. The result warns when a call could have hit this.

target="client" runs in the selected player's actual playtest client VM, including its live require cache. Requires a running playtest server studioId. Output is capped at 200 lines, 10 returns, table depth 4 and 50 entries. The relay is removed on completion or timeout; non-yielding code can still stall the client. Connections/hooks created by the temporary relay (such as Connect or RenderStepped) do not persist after the call returns.

target="live" runs the script on Roblox's servers against the PUBLISHED place instead, with no Studio involved. That is how you read or repair production: a real player's data store entry, what the live game actually holds, a migration over saved data. Everything the script prints comes back in logs.

BE CAREFUL WITH IT. The Studio path has an undo stack and a place nobody is playing. This one touches live data and live players, and nothing here can put any of it back — so it needs confirm: true and you should read before you write. Roblox queues it as a task, so expect seconds, not milliseconds, and a state of COMPLETE or FAILED rather than a bare value.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
playerNoclient only: player name; required with multiple players.
sourceYesLuau to run. In an editor session this has plugin permissions, so `game`, `workspace` and plugin-only APIs are all reachable.
targetNo'studio' runs in the connected Studio, with plugin permissions. 'live' runs on Roblox's servers against the published place — production, with no undo. 'client' runs in a player's playtest client VM.studio
confirmNoRequired for target="live". This runs against the game people are playing and nothing here can undo it.
placeIdNolive only: which place. Omit to use `cloud place`.
studioIdNoTarget Studio; omit for the active one.
universeIdNolive only: which game. Omit to use `cloud universe`.
timeoutSecondsNolive/client only: timeout in seconds. Defaults to 30.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.7.5
    • addedInput schema / properties / player
      Added value: +{
      +  "description": "client only: player name; required with multiple players.",
      +  "type": "string"
      +}
    • changedInput schema / properties / target / description
      Previous value: -"'studio' runs in the connected Studio, with plugin permissions. 'live' runs on Roblox's servers against the published place — production, with no undo."New value: +"'studio' runs in the connected Studio, with plugin permissions. 'live' runs on Roblox's servers against the published place — production, with no undo. 'client' runs in a player's playtest client VM."
    • changedInput schema / properties / target / enum
      Previous value: -[
      -  "studio",
      -  "live"
      -]New value: +[
      +  "studio",
      +  "live",
      +  "client"
      +]
    • changedInput schema / properties / timeoutSeconds / description
      Previous value: -"live only: how long the script may run. Defaults to 30."New value: +"live/client only: timeout in seconds. Defaults to 30."
  2. Changed5 schema fields changedv0.6.8
    • addedInput schema / properties / confirm
      Added value: +{
      +  "description": "Required for target=\"live\". This runs against the game people are playing and nothing here can undo it.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / placeId
      Added value: +{
      +  "description": "live only: which place. Omit to use `cloud place`.",
      +  "type": "string"
      +}
    • addedInput schema / properties / target
      Added value: +{
      +  "default": "studio",
      +  "description": "'studio' runs in the connected Studio, with plugin permissions. 'live' runs on Roblox's servers against the published place — production, with no undo.",
      +  "enum": [
      +    "studio",
      +    "live"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / timeoutSeconds
      Added value: +{
      +  "description": "live only: how long the script may run. Defaults to 30.",
      +  "maximum": 300,
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • addedInput schema / properties / universeId
      Added value: +{
      +  "description": "live only: which game. Omit to use `cloud universe`.",
      +  "type": "string"
      +}
  3. First observedv0.1.8

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description carries an enormous amount of behavioral disclosure well beyond the readOnlyHint/destructiveHint annotations: input is not validated, writes may not be undoable as one step, no timeout on target='studio' (infinite loop hangs Studio), output caps (200 lines, 10 returns, table depth 4), the module-cache duplicate-copy problem with require, loadstring being disabled on playtest servers, relay cleanup, and the live-data danger requiring confirm. This all aligns with destructiveHint=true and readOnlyHint=false — no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but length is justified for an escape-hatch tool that can hang a Studio session or mutate live production data. The highest-stakes warnings ('BE CAREFUL WITH IT', the live-data danger, confirm requirement) are front-loaded and surfaced in caps; each paragraph covers a distinct concern (usage, output, require caveat, per-target behavior) with no redundancy. Slightly more than needed, but every sentence earns its place given the blast radius.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and wildly variable return values, the description must explain return behavior on its own — and it does: print is captured and returned, return works for tables as structures, output caps are specified, and live returns a state of COMPLETE/FAILED rather than a bare value. It covers all three target modes, their prerequisites (running playtest server, published place), the exact caveats for each, and the confirmation flow. Nothing an agent needs to invoke this safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds substantial semantic depth beyond the schema: it explains what each target actually means in practice ('live' runs against the PUBLISHED place with no undo; 'client' runs in the player's playtest VM with a live require cache), why confirm is mandatory for live, what timeouts imply, and that source carries plugin permissions. This meaningfully exceeds what the schema's property strings convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Runs Luau in Studio's plugin context') and immediately frames it as 'the escape hatch' — the tool you reach for when dedicated tools don't fit. It explicitly names the siblings it is not (create, modify, delete, move, script_edit, find) and contrasts its behavior against them. An agent can unambiguously distinguish this from every one of the 34 siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance ('reading something no tool exposes, a one-off calculation, calling an engine API the tools do not cover') and when-not-to ('only when no dedicated tool fits'). It further sub-divides usage by target: 'live' is for production reads/repairs, and it warns against using require for live state. No other tool in the sibling list gets this level of routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.