# Studio MCP tools

> Every tool of Disko Studio's MCP server with its arguments.

The tools of the server at `https://studio.disko.ooo/mcp`. To connect an
assistant, see [Connect an AI assistant](/agents/studio-mcp). Each call is
one step in the project's history, marked as the agent's in the editor's
History panel, where people can undo it.

## Protocol

- Transport: Streamable HTTP.
- Authorization: an OAuth 2.1 protected resource. An unauthenticated
  request gets `401` with the resource metadata address. Clients sign the
  person in through disko's authorization server with the pre-registered
  public client `disko-mcp` (PKCE). Redirects may go to `localhost` or
  `127.0.0.1` on any port, or to Claude's and ChatGPT's connector callbacks.
- A call without its scope gets `403 insufficient_scope` naming the scope.

| Scope          | Tools                                                                     |
| -------------- | ------------------------------------------------------------------------- |
| `studio:read`  | `list_projects`, `open_project`, `get_document`, `vocabulary`, `validate` |
| `studio:write` | `create_project`, the edit tools, `undo`, `publish`                       |
| `studio:play`  | `play`, `screenshot`, `replay`                                            |

## A working loop

1. `vocabulary` for the triggers, conditions, actions and UI primitives.
2. `get_document` with the outline view for the objects and their ids.
3. `create`, `set`, `add_row` and `add_ui_node` to build. Properties that
   hold expressions take text: `(0, 0)`, `score + 1`.
4. `validate` until there are no problems.
5. `play` with scripted players, and `screenshot` to see the field.
6. `publish` when the person asks.

## Tools

This page is generated from the MCP server's tool definitions.

### list_projects

The account's Disko Studio projects: id, name, last change.

No arguments.

### create_project

Creates a project for the account and returns its id. `template` "starter" starts it as a game that plays: teams, a Menu that runs the match, a score and a clock, and a disc with a kick for each player (add the ball and the rules); "blank" (the default) starts it empty.

| Argument | Type | Required |
| --- | --- | --- |
| `name` | string | yes |
| `template` | "starter" \\| "blank" or none | no |

### open_project

Opens a project for editing (live in the editor) and returns its outline: one line per object with its id.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |

### get_document

The project's document: `outline` (a readable tree with ids) or `full` (every object as JSON); `ids` limits `full` to those objects.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `view` | "outline" \\| "full" | yes |
| `ids` | list of string or none | no |

### validate

The project's problems, each with a stable code and the ids of the objects it is on.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |

### vocabulary

The event sheet's vocabulary (triggers, conditions, actions with their slots) and the UI primitives with their options.

| Argument | Type | Required |
| --- | --- | --- |
| `part` | "trigger" \\| "condition" \\| "action" \\| "ui" | yes |

### undo

Undoes this agent's last step on the project (a new op; others' later edits are kept).

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |

### create

Creates an object of `kind` under `parent` (null for the project's top level) with the kind's defaults, `name` and `props`. Expression-valued properties take text: `(0, 0)`, `Ball.position`, `score + 1`.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `kind` | "settings" \\| "scene" \\| "disc" \\| "wall" \\| "joint" \\| "crossing" \\| "visual" \\| "camera" \\| "prefab" \\| "instance" \\| "asset" \\| "enumeration" \\| "variable" \\| "expression" \\| "custom-event" \\| "event-group" \\| "event-row" \\| "condition" \\| "action" \\| "action-schema" \\| "action-def" \\| "role" \\| "script" \\| "ui-screen" \\| "ui-node" \\| "ui-style" \\| "ui-theme" | yes |
| `parent` | string or none | yes |
| `name` | string or none | no |
| `props` | record or none | no |

### set

Sets one property (`path` is a property, or `property.key` inside a record) of an object. Expression-valued properties take text.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `id` | string | yes |
| `path` | string | yes |
| `value` | value | yes |

### instantiate_prefab

Places an instance of a prefab in a scene at (x, y).

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `scene` | string | yes |
| `prefab` | string | yes |
| `x` | number | yes |
| `y` | number | yes |
| `name` | string or none | no |

### apply_ops

Applies raw document ops (create, set, move, delete, batch) as one step: for anything the typed tools do not cover.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `label` | string | yes |
| `ops` | list of { op, id, kind, placement, props } or { op, id, snapshot } or { op, id, path, value, prev } or { op, id, placement, prev } or { op, label, ops } | yes |

### rename

Renames an object (references use ids, so nothing breaks).

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `id` | string | yes |
| `name` | string | yes |

### move

Moves an object under `parent` (null: top level) at `index` among its children (default: last).

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `id` | string | yes |
| `parent` | string or none | yes |
| `index` | integer or none | no |

### delete

Deletes an object and everything inside it.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `id` | string | yes |

### add_row

Adds a row to the event sheet: When `trigger`, If `conditions`, Do `actions` (items from `vocabulary`; slots as text expressions that may use the trigger's names, e.g. `player`). `parent` is a group, or a row for a sub-row with `sub` (otherwise, if, after).

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `parent` | string or none or none | no |
| `sub` | "otherwise" \\| "if" \\| "after" or none | no |
| `after` | string or none | no |
| `trigger` | { item, slots } or none | no |
| `conditions` | list of { item, slots, not } or none | no |
| `actions` | list of { item, slots } or none | no |
| `comment` | string or none | no |

### add_ui_node

Adds a `ui.*` node to the Menu or the HUD under `parent` (a node id; omitted: the screen's top level). Options and style values are text expressions (`"Join"`, `score`, `t.name` inside a repeater over an enumeration as `t`). `activate` sends a `ui-request` named `request`. `audience` is an audience expression (`withRole(host)`, `players(Team(Red))`, `anyOf(withRole(host), withRole(referee))`, `except(everyone, [viewer])`; never `near`, a node has no position): only its players receive the node, recomputed as it changes; `outside: "disabled"` shows it disabled to everyone else instead of hiding it.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `screen` | "menu" \\| "hud" | yes |
| `parent` | string or none | no |
| `primitive` | "box" \\| "stack" \\| "row" \\| "grid" \\| "overlay" \\| "scroll" \\| "spacer" \\| "text" \\| "richtext" \\| "image" \\| "icon" \\| "shape" \\| "button" \\| "link" \\| "form" \\| "input" \\| "area" \\| "toggle" \\| "slider" \\| "select" \\| "option" \\| "progress" \\| "activity" \\| "status" \\| "alert" \\| "list" \\| "item" \\| "table" \\| "header" \\| "body" \\| "footer" \\| "cell" \\| "modal" \\| "popover" \\| "tabs" \\| "tab" \\| "panel" \\| "disclosure" \\| "flag" \\| "connection" \\| "playerName" | yes |
| `name` | string or none | no |
| `options` | record or none | no |
| `style` | record or none | no |
| `repeat` | { over, as, where } or none | no |
| `activate` | { request, values, requires } or none | no |
| `audience` | string or none | no |
| `outside` | "hidden" \\| "disabled" or none | no |

### play

Runs the project for `ticks` (60 per second, real time) in an offline room with scripted players (roles, held directions over tick ranges, UI controls by author key), then returns the events, the variables and each player's bodies.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `ticks` | integer | yes |
| `start` | boolean or none | no |
| `players` | list of { name, roles, enter, inputs, controls } or none | no |

### screenshot

Runs the project like `play` and returns what the first player sees at the end, drawn by the client's painter.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `ticks` | integer | yes |
| `start` | boolean or none | no |
| `players` | list of { name, roles, enter, inputs, controls } or none | no |

### replay

Runs the project like `play` while recording, and returns the replay file (opens in the client's replay viewer).

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `ticks` | integer | yes |
| `start` | boolean or none | no |
| `players` | list of { name, roles, enter, inputs, controls } or none | no |

### publish

Publishes the project to the registry as `game` (`namespace/slug`, a namespace the account owns) at the version in its settings, as `public`, `unlisted` or `private`.

| Argument | Type | Required |
| --- | --- | --- |
| `project` | string | yes |
| `game` | string | yes |
| `visibility` | "public" \\| "unlisted" \\| "private" | yes |
