Roblox Studio MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| resources | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| studio_statusA | One-call snapshot of the connected Roblox Studio: place name and id, whether it is in edit / run / play mode, the current selection, which scripts are open in the editor, and how big the data model is. Call this FIRST in any Studio session, and again whenever a tool reports NO_STUDIO or TIMEOUT — it is the cheapest way to tell a disconnected plugin apart from a genuinely failing request. Also call it before and after
Returns JSON. Selection is capped at 50 entries and selected text at 400 characters; use |
| list_studiosA | Lists every Roblox Studio window currently connected to this server, with its studioId, place name, transport (sse or poll), when it connected, and which one is active. Call this whenever a tool reports AMBIGUOUS_STUDIO, and whenever the user refers to 'the other place' or 'my other window'. With a single Studio open every other tool targets it automatically, so you can skip it then. Nothing is targeted by default when several are connected: pick one with Each Studio is queried live, so
|
| set_active_studioA | Chooses which connected Studio window every other tool targets by default. Use it after list_studios when several places are open, and again whenever the user says to switch to another place. The choice persists until it is changed or that Studio disconnects. While several Studios are connected and none has been chosen, tools refuse with AMBIGUOUS_STUDIO rather than guessing. The choice belongs to this MCP connection alone. Several agents can share one Studio, and each keeps its own target, so calling this never moves another client's — two editors, or two sessions, can work on two places at once. SUBAGENTS SHARE THEIR PARENT'S CONNECTION, and therefore its target. A subagent calling this retargets its parent and every sibling, and the damage is silent: later calls that name no studioId still succeed, just against the wrong place — and if that place is a playtest, everything written there is discarded when it stops. Inside a subagent, pass |
| treeA | Lists the instance hierarchy under a path, breadth-first to a given depth. Returns a flat array of paths — flat is both cheaper and easier to act on than nested JSON, since every entry is directly usable as a path. Use this to orient yourself in an unfamiliar place. Use With |
| inspectA | Reads properties, attributes, tags and children of one or more instances. Pass every path you care about in a single call — batching costs one round trip instead of N. Property selection comes from the live Roblox API dump for each instance's actual class, so it stays correct across engine updates: concise — class and child count only standard — the properties that characterise the class (Part gets Size, Position, CFrame, Anchored, Material...) full — every readable property; expensive, use on one or two instances at most Bad paths do not fail the call: they come back under |
| findA | Searches the data model by name, class, property value and/or tag. Every filter you supply must match, so one call answers questions that would otherwise take several: "anchored BaseParts under Workspace.Map whose name contains door" is a single request. This replaces separate name / class / property / tag search tools. Prefer it over Tag searches are answered from CollectionService's index rather than by walking the tree, so they stay fast on large places. Narrow with |
| script_readA | Reads Luau source from one or more scripts, with line numbers that Source comes from the Studio script editor's live buffer, so anything the user has typed but not yet saved is included. Reading the saved property instead would hand you stale code and you would 'fix' the change they just made. Pass every script you need in one call. |
| script_editA | Edits Luau source through the Studio script editor. This is the tool to use for any change to existing code. Every edit in one call is all-or-nothing: the whole batch is resolved against current source before anything is written, so if one edit cannot be applied nothing is. Batch related changes together, even across different scripts. Each edit picks exactly one mode:
find/replace — literal text, not a pattern. Preferred: it survives line numbers shifting. Fails if the text is not unique, unless you set Writes go through |
| script_grepA | Searches inside Luau source across the place and returns matching lines with their paths and line numbers. Use this to find where something is defined or used before editing it — it is far cheaper than reading whole scripts to look for one call. Patterns are Lua patterns, which are not regular expressions: Matches come from the script editor's live buffer, so unsaved edits are searched too. |
| script_createA | Creates Script, LocalScript or ModuleScript instances with their source. Batch related scripts into one call: they are created inside one ChangeHistoryService recording, so the user can drop a whole generated system in a single undo. The response says whether that recording was actually opened — Studio refuses while another one is in progress. Prefer |
| createA | Creates instances with their properties, attributes and tags set at creation, as one undoable step. Nest with Property names are checked against the live Roblox API dump before anything is sent to Studio, so a typo comes back with the closest real names rather than an engine error. Use |
| modifyA | Sets properties, attributes and tags on existing instances, as one undoable step. Each entry takes a list of The batch is all-or-nothing: if any value is rejected the recording is cancelled and every instance reverts, rather than leaving the place half-changed. Values use the same notation the Properties panel shows — see the |
| deleteA | Destroys instances and everything inside them, as one undoable step. Deleting a container deletes its whole subtree, so the response reports how many descendants went with each one — check it before telling the user what happened. Services cannot be deleted and are refused. Paths shift when same-named siblings are removed, so read fresh paths from |
| moveA | Reparents instances, or clones them into a new parent, as one undoable step. Set Moving an instance into itself or its own descendant is refused: it silently detaches the branch from the data model and undo does not bring it back. |
| consoleA | Reads the Studio Output window — prints, warnings and runtime errors, newest last. This is how to find out what actually happened after a playtest or an Filter with Each connected session keeps its own log, recorded from the moment its plugin loaded — the editor session and a running playtest server do not share one. To read what a playtest printed, target the playtest's studioId (see |
| performanceA | Reads the engine's own counters, and can run the script profiler.
What it can and cannot see: instrumentation is fixed when a script is first compiled, so it measures modules required after that point — where most game logic lives — but never a script that starts with the place, which the data model compiles before any plugin exists. Those report 0 lines and are named as unmeasurable rather than counted as dead code.
Frame and network figures are only meaningful while something is running. Instance counts and memory are useful in edit mode too. |
| playtestA | Starts and stops playtests, so scripts can be made to run and then observed without asking the user to press anything.
Pressing play adds a SECOND connected session for the playtest's server, and that is where the running game lives — A test does not block this call: it starts and the reply reports the state reached. Studio only ends it when something inside calls Stopping discards everything the playtest changed, exactly as pressing Stop does. Build in edit mode, then play — not the other way round. The reply says whether the mode actually moved, not merely that Studio accepted the request. |
| execute_luauA | 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 — 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 Against a running playtest server, Studio disables |
| viewportA | Works with the 3D view and the Studio selection.
The distance is computed from the subject's size and the camera's field of view, so a doorway and a whole map both arrive filling a similar share of the frame.
|
| debugA | Sets breakpoints that record the stack and variables when they are hit, then reads back what they caught. These are tracepoints, not a step debugger. A breakpoint fires, captures the call stack and the variables in scope, and lets execution continue;
So the two kinds cost different things: a Only one breakpoint exists per line, so the same line cannot both log and capture. Put the breakpoint on a line that does something. A Breakpoints belong to the session that holds them. Set them in the editor session BEFORE starting a playtest, since code that already ran cannot be caught retroactively. Nothing here leaves a thread stopped waiting for you. A capture breakpoint stops for as long as it takes to read the frame and then resumes itself, so a script with one mid-loop still runs to its last line, and the user is never left with a frozen Studio to rescue. |
| screenshotA | Takes a picture of the Studio viewport and returns it as an image you can actually look at. Every other tool here reads the data model — names, properties, numbers — which answers 'is it there' but never 'does it look right'. A part can be at the correct position, anchored, correctly sized, and still be buried inside a wall, facing backwards, or hidden behind a GUI. Take a screenshot after building something visual, and before reporting that it worked. It captures the viewport as the user currently sees it, so it shows their camera angle, not a framing of your choosing. Frame the subject with Works during a playtest too — address it at the playtest's studioId and you get the player's own view, which is the only way to check what a GUI actually looks like in front of the game. That one is taken on the client and read back through the editor session, so it is a little slower and needs the editor window still connected; the caption says |
| inputA | Sends real keyboard and mouse input to a running playtest — the same events a person pressing the keys would produce. This is how to test what Steps run in order, so a sequence is one call: tap E, wait, click at a point, type a name. REQUIRES A RUNNING PLAYTEST, and must be addressed to the playtest's studioId from A pointer is drawn on screen and travels to each target before the click, so the user can see what you are aiming at. Turn it off with How it works, because it explains the one thing that will surprise you: input belongs to the data model that creates it, and the character is driven by the CLIENT. Sending from the playtest's server succeeds and moves nothing. So this parents a short script into the player's PlayerGui, which runs on their client, and that reports back when the input has actually been delivered. Nothing is reported as sent until the client confirms it. If confirmation never arrives you get an error, not a success — check where things really are with Mouse coordinates are viewport pixels from the top-left, so pair this with |
| deviceA | Resizes the Studio viewport to a real device, so you can see what a player on that device sees. Most Roblox players are on a phone and most UI is built on a desktop monitor, which is where interfaces break: a button under the notch, a menu off the bottom of a 393-pixel-tall screen, text sized for a display three times larger. None of that is visible in the data model — every one of those instances has perfectly correct properties — so this is the only way to find it short of owning the hardware. The workflow is:
|
| apiA | Lists the properties, methods and events of any Roblox class, read from the engine that is running. Use it before writing Luau against a class you are not certain of. Guessing a method name costs a runtime error and a round trip; this costs one call and is never out of date, because the answer comes from the running binary rather than from a published dump or from training data. That matters most for exactly the classes worth checking — new ones, and ones that changed recently. Members come back as signatures rather than bare names —
Deprecated members are never listed, only counted — This is not the same as |
| geometryA | Cuts, joins and shatters parts with real constructive solid geometry. This is how to build a shape that is not a box without importing a mesh:
Results keep the original's material, colour and anchoring. Roblox returns bare grey MeshParts, so a brick wall with a hole cut in it would otherwise come back as a grey slab — correct geometry that looks like a mistake. The originals are consumed unless |
| assetsA | Searches Roblox's Creator Store and inserts models into the place.
ALWAYS check Only public assets can be inserted. A private or deleted id fails with a message saying so rather than inserting nothing quietly. |
| undoA | Steps Studio's undo history backwards or forwards. Every write this server makes is already wrapped in an undo recording, so this reverses your own work as cleanly as the user pressing Ctrl+Z — one tool call is one step. Use it when the user says an edit was wrong, instead of trying to reconstruct the previous state by hand, which is guesswork and usually incomplete. It reports how many steps actually applied, which is not always what was asked: the stack runs out, and an undo that did nothing otherwise looks exactly like one that worked. Studio's history covers the whole session, including the user's own edits — undoing more steps than you made will start reverting THEIR work. Undo only what you just did, and only when asked. |
| collisionA | Controls which parts physically collide with which. This is the right answer to 'these should pass through each other'. The alternative — turning CanCollide off — disables collision against everything, so a ghost that should pass through walls also falls through the floor. The order is: Assigning a Model assigns every part inside it, which is almost always what is meant. Groups are not undoable and not scoped to a session: |
| characterA | Moves and acts as the player character in a running playtest, so gameplay can be tested without asking the user to play it.
This drives the Humanoid directly rather than simulating keystrokes, which is the right tool for going places: pathfinding around a wall is one call here and a sequence of guessed key presses otherwise. For anything bound to a control rather than to movement — does E open the door, does the sprint key work, does Escape close the menu — use REQUIRES A RUNNING PLAYTEST, and the character lives in the playtest's data model — address these to the playtest's studioId from |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| studio-status | Which place is open, whether it is playing, what is selected, and which scripts the user has on screen. The cheapest orientation there is. |
| studio-tree | The authored containers and what is directly inside them, two levels deep. A map of the place, without the ~120 engine services that would bury it. |
| studio-console | The last 100 lines Studio printed, warnings and errors included. Reading this after a playtest is usually the first useful thing to do. |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/EL4CTEO/rbx-studio-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server