Skip to main content
Glama
EL4CTEO

Roblox Studio MCP

Viewport and selection

viewport
Idempotent

Control Studio's 3D view and selection: focus the camera, select instances, raycast, audit UI, measure text, and snapshot interfaces to verify Roblox builds visually.

Instructions

Works with the 3D view and the Studio selection.

select sets, extends or shrinks what is highlighted in Studio. Select what you just built or changed — it shows the user the result, and puts the instance under Studio's own move and scale handles. studio_status reports the current selection; this sets it.

focus aims the Studio camera at an instance and frames it so the whole thing is on screen. This is what makes screenshot worth having: a picture of wherever the camera happened to be answers nothing, while a picture of the thing you just built answers 'does it look right', which no amount of reading properties can. Build, focus, screenshot.

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. from changes the angle you view it from, and padding how tightly it is framed.

camera sets or reads the camera directly, for shots framing cannot express — standing inside a room, or looking along a corridor.

raycast fires a ray through the world and reports the first thing it hits, with position, surface normal, distance and material. This answers 'what occupies this space', which the data model alone cannot: use it to find the ground under a spawn point, or check whether a gap is clear before placing something.

ui audits a whole interface for the faults that are invisible in the data model: elements off the side of the screen, elements covering each other, zero-size elements, text too small to read, and text that overflows its label. A button positioned off a phone screen has a perfectly correct Position and Size — nothing about the instance is wrong, it is just somewhere nobody can reach.

It measures against whatever device is currently emulating, so the way to use it is twice: once as-is, then device op="set" a phone and again. Layout is live in edit mode — no playtest needed.

textbounds measures how big a piece of text actually renders. Point it at a TextLabel, TextButton or TextBox with path and it reads that label's own text, font, size and width and answers whether the text fits inside it. Give text and size directly and it just measures. There is no other honest way to answer 'will this label overflow' — character counts ignore the font, and font size is not a width.

uisnap records every UI element under path (default StarterGui, or the PlayerGui with target="client"): layout, absolute position and size, colours, fonts, text, images, strokes, corners and padding, and returns a snapshot id. Take one before restyling a UI, then call uisnap again with compareTo set to that id: the reply lists what was added, removed and changed, property by property, including what you did not mean to touch. Every call stores a new id, so passes chain.

Input Schema

NameRequiredDescriptionDefault
xNopick: normalized X in the full uncropped viewport.
yNopick: normalized Y in the full uncropped viewport.
atNofocus only: look at this point instead of an instance, e.g. "0, 10, 0".
opYes'focus' points the camera at something and frames it, 'camera' sets it explicitly, 'select' changes the Studio selection, 'textbounds' measures rendered text, 'raycast' queries the world, 'ui' audits an interface, 'uisnap' snapshots one and diffs it against an earlier snapshot.
fontNotextbounds only: an Enum.Font name, e.g. "GothamMedium". Defaults to the label's.
fromNofocus only: direction to view from, e.g. "0, 1, 0" for directly above or "1, 0, 0" from the side. Defaults to a raised three-quarter view.
modeNoselect only: replace the selection, extend it, or remove from it.set
pathNofocus: the instance to look at. ui/uisnap: the UI root to read. textbounds: the label.
textNotextbounds only: the string to measure. Defaults to the label's own text.
pathsNoselect only: instances to select. An empty array clears the selection.
ignoreNoraycast only: instances the ray passes through.
lookAtNocamera only: the point to aim at.
originNoraycast only: where the ray starts, e.g. "0, 50, 0".
playerNoclient only: player name; required with multiple players.
targetNoclient: read the actual player's playtest VM. Use the playtest server studioId.studio
paddingNofocus only: how much room to leave around the subject. 1 is tight.
positionNocamera only: where to put the camera, e.g. "0, 20, 30".
richTextNotextbounds only: treat the text as rich text. Defaults to the label's setting.
studioIdNoTarget Studio; omit for the active one.
textSizeNotextbounds only: font size in pixels. Defaults to the label's.
compareToNouisnap only: id of an earlier snapshot to diff the new one against.
directionNoraycast only: which way it points, e.g. "0, -1, 0" for straight down.
wrapWidthNotextbounds only: wrap at this width. 0 means do not wrap. Defaults to the label's width.
fieldOfViewNocamera only: field of view in degrees. Lower is more zoomed in.
maxDistanceNoraycast only: how far to look, in studs.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.9.5
    • addedInput schema / properties / compareTo
      Added value: +{
      +  "description": "uisnap only: id of an earlier snapshot to diff the new one against.",
      +  "type": "string"
      +}
    • changedInput schema / properties / op / description
      Previous value: -"'focus' points the camera at something and frames it, 'camera' sets it explicitly, 'select' changes the Studio selection, 'textbounds' measures rendered text, 'raycast' queries the world."New value: +"'focus' points the camera at something and frames it, 'camera' sets it explicitly, 'select' changes the Studio selection, 'textbounds' measures rendered text, 'raycast' queries the world, 'ui' audits an interface, 'uisnap' snapshots one and diffs it against an earlier snapshot."
    • changedInput schema / properties / op / enum
      Previous value: -[
      -  "select",
      -  "raycast",
      -  "focus",
      -  "camera",
      -  "textbounds",
      -  "ui",
      -  "pick"
      -]New value: +[
      +  "select",
      +  "raycast",
      +  "focus",
      +  "camera",
      +  "textbounds",
      +  "ui",
      +  "uisnap",
      +  "pick"
      +]
    • changedInput schema / properties / path / description
      Previous value: -"focus only: the instance to look at. A model, part, or folder containing them."New value: +"focus: the instance to look at. ui/uisnap: the UI root to read. textbounds: the label."
  2. Changed5 schema fields changedv0.9.1
    • changedInput schema / properties / op / enum
      Previous value: -[
      -  "select",
      -  "raycast",
      -  "focus",
      -  "camera",
      -  "textbounds",
      -  "ui"
      -]New value: +[
      +  "select",
      +  "raycast",
      +  "focus",
      +  "camera",
      +  "textbounds",
      +  "ui",
      +  "pick"
      +]
    • addedInput schema / properties / player
      Added value: +{
      +  "description": "client only: player name; required with multiple players.",
      +  "type": "string"
      +}
    • addedInput schema / properties / target
      Added value: +{
      +  "default": "studio",
      +  "description": "client: read the actual player's playtest VM. Use the playtest server studioId.",
      +  "enum": [
      +    "studio",
      +    "client"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / x
      Added value: +{
      +  "description": "pick: normalized X in the full uncropped viewport.",
      +  "maximum": 1,
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / y
      Added value: +{
      +  "description": "pick: normalized Y in the full uncropped viewport.",
      +  "maximum": 1,
      +  "minimum": 0,
      +  "type": "number"
      +}
  3. Changed1 schema field changedv0.6.5
    • changedInput schema / properties / op / enum
      Previous value: -[
      -  "select",
      -  "raycast",
      -  "focus",
      -  "camera",
      -  "textbounds"
      -]New value: +[
      +  "select",
      +  "raycast",
      +  "focus",
      +  "camera",
      +  "textbounds",
      +  "ui"
      +]
  4. Changed7 schema fields changedv0.4.5
    • addedInput schema / properties / font
      Added value: +{
      +  "description": "textbounds only: an Enum.Font name, e.g. \"GothamMedium\". Defaults to the label's.",
      +  "type": "string"
      +}
    • changedInput schema / properties / op / description
      Previous value: -"'focus' points the camera at something and frames it, 'camera' sets it explicitly, 'select' changes the Studio selection, 'raycast' queries the world."New value: +"'focus' points the camera at something and frames it, 'camera' sets it explicitly, 'select' changes the Studio selection, 'textbounds' measures rendered text, 'raycast' queries the world."
    • changedInput schema / properties / op / enum
      Previous value: -[
      -  "select",
      -  "raycast",
      -  "focus",
      -  "camera"
      -]New value: +[
      +  "select",
      +  "raycast",
      +  "focus",
      +  "camera",
      +  "textbounds"
      +]
    • addedInput schema / properties / richText
      Added value: +{
      +  "description": "textbounds only: treat the text as rich text. Defaults to the label's setting.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / text
      Added value: +{
      +  "description": "textbounds only: the string to measure. Defaults to the label's own text.",
      +  "type": "string"
      +}
    • addedInput schema / properties / textSize
      Added value: +{
      +  "description": "textbounds only: font size in pixels. Defaults to the label's.",
      +  "maximum": 200,
      +  "minimum": 1,
      +  "type": "number"
      +}
    • addedInput schema / properties / wrapWidth
      Added value: +{
      +  "description": "textbounds only: wrap at this width. 0 means do not wrap. Defaults to the label's width.",
      +  "minimum": 0,
      +  "type": "number"
      +}
  5. 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 adds substantial behavioral context beyond the annotations: focus distance is computed from subject size and field of view, layout checks are live in edit mode, every `uisnap` call stores a new id, and diffs include accidental changes. These details explain what the operations actually do and what effects they leave behind. The annotations' `readOnlyHint: false` is consistent with the selection and camera mutation operations described.

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 length is justified by eight distinct operations and 25 parameters, and the description is organized into clear per-operation paragraphs. Some prose is rhetorically inflated, such as 'no amount of reading properties can' and 'There is no other honest way', which adds persuasion rather than operational detail. Overall it remains well structured and front-loads the main operations.

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?

For a complex multiplexed tool with no output schema, the description is unusually complete: it describes what `raycast` returns, what `uisnap` returns and diffs, what `ui` audits, what `textbounds` answers, and how selection and camera operations behave. An agent has enough information to choose the right `op` and understand the result shape without additional documentation.

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 description coverage is already 100%, so the schema documents all 25 parameters, including per-operation meanings. The description adds useful cross-operation semantics, such as what `focus` computes from size and field of view, how `padding` affects framing, and what `from` changes. It stops short of explaining every parameter, but the schema carries that burden well.

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 opens with a precise scope statement and then defines each of the eight operations with a concrete verb and resource: selecting instances, aiming the camera, reading/setting the camera, raycasting, auditing UI, measuring text bounds, and diffing UI snapshots. It clearly distinguishes this tool from siblings like `screenshot` and `studio_status` by explaining what each contributes that the others do not.

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?

Usage guidance is explicit throughout: use `focus` before `screenshot`, use `ui` once as-is and again after changing `device`, take a `uisnap` before restyling and diff with `compareTo` afterward, and use `raycast` to find ground under a spawn point or check clearance. The description also names the limits of alternatives such as reading properties or counting characters, so an agent can decide which operation applies.

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