Roblox Studio MCP supports any number of Studio windows connected to the same server simultaneously — two games open side by side, a published place alongside a local prototype, or a full playtest with separate edit, server, and client DataModels all registered at once. Every MCP tool call must ultimately execute inside exactly one Studio DataModel, so the server needs a way to decide which one. That decision is called routing, andDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Chrrxs/robloxstudio-mcp/llms.txt
Use this file to discover all available pages before exploring further.
instance_id is the parameter that controls it.
How instanceId Is Assigned
When a Studio plugin loads, it calls /ready and provides the server with its placeId, placeName, and a self-generated instanceId. The server normalizes this into a canonical routing key:
- Published places (
placeId > 0):"place:<PlaceId>"— for example"place:12345678". All DataModel roles for the same published place share this key. - Unpublished / local places (
placeId == 0):"anon:<uuid>"— the UUID is persisted as the__MCPPlaceIdattribute onServerStorageinside the.rbxlfile, so it travels with the file. Re-opening the same local file returns the sameinstanceIdacross server restarts.
pluginSessionId (an internal per-plugin GUID, regenerated on every plugin load) is used only inside the server as a map key — it is never exposed to MCP tool callers.
Discovering Connected Instances
Before routing, you can callget_connected_instances to see everything the server knows about:
isRunning field becomes true when a playtest is active in that window. versionMismatch flags a plugin/server version difference that may affect tool behavior.
The instance_id Parameter
Every tool in the catalog includes an instance_id parameter in its inputSchema. The routing rules are:
- One place connected
- Multiple places connected
- Playtest with multiple roles
Omit
instance_id. The server routes automatically to the only connected instance. Passing it is harmless.The target / Role Parameter
During a playtest, a single instanceId (place) has multiple connected DataModel peers:
| Role | DataModel | When present |
|---|---|---|
edit | Editable DataModel | Always (not during multiplayer test) |
server | Play-server DataModel | During any playtest |
client-1 | First play-client DataModel | During play mode or multiplayer test |
client-2 | Second play-client DataModel | During multiplayer test with ≥ 2 players |
client-N | Nth play-client | As above |
execute_luau, get_runtime_logs, eval_server_runtime) accept a target parameter. When instance_id is provided and the target role is present, routing resolves to a single (instanceId, role) tuple. When target is omitted and only one role is connected for that instanceId, routing resolves automatically. If multiple roles are connected and target is omitted, the server prefers edit if present; otherwise it returns a target_role_required error.
Passing target="all" triggers fanout — the tool runs against every role simultaneously and returns aggregated results.
Routing Error Codes
Routing failures return structured JSON that embeds the full current instance list. The AI agent can recover by readingdata.instances and retrying with the correct instance_id — no extra round-trip required.
bridge-service.ts:
| Code | Cause | Resolution |
|---|---|---|
multiple_instances_connected | More than one distinct place is connected and instance_id was omitted | Pass instance_id from data.instances |
ambiguous_target | Multiple places are connected, a target role was specified, but no instance_id | Pass instance_id to select the place |
target_role_required | instance_id is valid but the place has multiple roles connected and target was omitted (and no edit role to default to) | Pass target=<role> using the available roles listed in the error message |
target_role_not_present_on_instance | instance_id is valid but the specified target role is not connected for that instance | Check data.instances for available roles; start a playtest if the runtime role is needed |
unrecognized_instance_id | The provided instance_id does not match any connected plugin | Check data.instances for valid IDs; the place may have been closed or not yet connected |
Routing errors arrive as
isError: true tool results with a JSON body — not as MCP protocol errors. The agent can parse the error code and data.instances array inline without invoking a separate tool.Stale Instance Cleanup
The server considers an instance stale if it has not polled/poll within 30 seconds. Stale instances are automatically unregistered during the periodic cleanup cycle (every 5 seconds). Any pending requests targeting a stale instance are rejected immediately with "Target disconnected". This prevents tool calls from hanging when Studio is minimized or the plugin crashes.
Instance aliases (anon: → place: transitions when a local file is published mid-session) are retained for up to 5 minutes after the last-seen timestamp before being pruned.
Example: Routing Tool Calls Across Two Open Places
The following scenario shows how to work with two simultaneously open Studio windows.Anonymous Place IDs and the __MCPPlaceId Attribute
For unpublished places, the plugin stores the generated UUID as a StringValue-style attribute named __MCPPlaceId on ServerStorage. Because this attribute is part of the DataModel, it is saved when you save the .rbxl file. The same anon:<uuid> value is used every time that file is opened, even across MCP server restarts, so scripts or workflows referencing a local prototype’s instance_id remain stable across sessions.