Content
# Roickbot
[](https://github.com/TonyD365/Roickbot/actions/workflows/ci.yml)
[](https://github.com/TonyD365/Roickbot/releases/latest)
[](https://github.com/TonyD365/Roickbot/releases)
[](https://github.com/TonyD365/Roickbot/releases/latest)
[](https://github.com/TonyD365/Roickbot/stargazers)
[](https://github.com/TonyD365/Roickbot/commits)
[](LICENSE)
A desktop app + MCP server that lets **Claude Code — and any other MCP client (Gemini, Cursor,
VS Code, …)** — control **Roblox Studio**. Your AI can
read and edit scripts, inspect and modify the scene and models, run the simulation, and — in later
phases — build graphics and drive an in-game **Bot** that reports what it "sees" as structured data,
all through natural language from your editor.
> **Status:** v1.0.0 released. Phase 1 (core) and Phase 2 (make-graphics) are complete — a
> working, secured bridge with tools for scripts, instances, properties, selection, run/test,
> and building scenes (parts, terrain, lighting, decals, models, GUI), plus a universal
> `run_luau` escape hatch. Phase 3 (Bot vision) is next. Cross-platform installers with
> auto-update are published on the [Releases](https://github.com/TonyD365/Roickbot/releases) page.
## Table of contents
- [Features](#features)
- [How it works](#how-it-works)
- [Repository layout](#repository-layout)
- [Installation (end user)](#installation-end-user)
- [Development](#development)
- [Available tools](#available-tools)
- [Use with other AI clients](#use-with-other-ai-clients)
- [Security](#security)
- ["Think before acting"](#think-before-acting)
- [Roadmap](#roadmap)
- [License](#license)
## Features
- **Edit anything in Studio** — create / delete / clone / reparent instances, read and write any
property, and edit script source via `ScriptEditorService`.
- **Inspect the scene** — walk the DataModel tree, lazily expand large places, and pull detailed,
structured views of specific elements (Parts, Scripts, …).
- **Run & test** — start / stop / pause the physics simulation (`RunService`) and query the run
state.
- **Universal escape hatch** — `run_luau` executes arbitrary Luau in Studio for anything the typed
tools don't cover; effects are undoable.
- **Safe by design** — every change is a single undo waypoint, destructive ops require a dry-run
preview + confirmation (Claude-facing, no user pop-ups), and Core services are never mutable.
- **Secure local bridge** — loopback-only, random per-session Bearer token, `Host`/`Origin`
validation, and a required custom header to defend against malicious web pages.
- **One-click setup** — a desktop app starts the service, shows the pairing token, installs the
plugin, and writes the Claude Code MCP config for you.
- **Works with any MCP client** — not just Claude: Gemini, Cursor, VS Code/Copilot, Cline, etc.
(incl. free options). See [docs/CLIENTS.md](docs/CLIENTS.md).
- **Cross-platform releases** — CI packages installers: a macOS **Universal** app (Intel + Apple
Silicon) and a Windows x64 installer (runs on Intel and ARM).
## How it works
```
Claude Code (VSCode)
│ MCP over local HTTP/SSE (127.0.0.1, Bearer token)
▼
Desktop app (Electron)
├─ MCP server (@modelcontextprotocol/sdk, Streamable HTTP)
├─ Studio bridge (127.0.0.1, WebSocket)
└─ token / pairing / auth
▲ WebSocket /ws (persistent, bidirectional)
▼
Roblox Studio plugin (Luau) — runs commands on the DataModel
```
The Studio plugin connects to the bridge over a **WebSocket** (Studio's
`HttpService:CreateWebStreamClient`), a persistent two-way channel: the server pushes commands
instantly and the plugin streams back results and events — so there's no polling gap, and a dropped
connection is detected immediately. The desktop app owns the service lifecycle, hosts both the MCP
endpoint (for Claude Code) and the bridge (for the plugin), and helps you connect everything. Because
Luau also cannot read real screen pixels, "vision" (Phase 3) is delivered as structured data (raycast
hits + nearby objects), not images.
See [docs/PROTOCOL.md](docs/PROTOCOL.md) for the full wire protocol.
## Repository layout
| Path | What |
| --- | --- |
| `packages/core` | MCP server + HTTP bridge + security + command queue (TypeScript) |
| `packages/desktop` | Electron desktop app (start/stop service, pairing, install helpers) |
| `plugin` | Roblox Studio plugin (Luau, built with Rojo) |
| `docs` | [Install](docs/INSTALL.md), [protocol](docs/PROTOCOL.md), [tools](docs/TOOLS.md), [security](docs/SECURITY.md) |
| `smoke.mjs` | End-to-end bridge smoke test (no Studio required) |
## Installation (end user)
1. **Install the desktop app** from the
[Releases](https://github.com/TonyD365/Roickbot/releases) page — a macOS `.dmg`
(Universal: Intel + Apple Silicon) or a Windows `.exe` (x64, runs on Intel and ARM).
2. **Start the service** in the app, pick your client from the dropdown (Claude Code, Cursor,
Gemini CLI, Cline, VS Code) and click **Install MCP config** — the app writes the `roickbot`
server in that client's exact format and location for you. Then restart the client.
3. **Install the plugin**: if it shows offline, click **Install plugin** and save
`Roickbot.rbxmx` into your Studio Plugins folder.
4. **Enable HTTP** in Studio's Command Bar (once per place):
`game:GetService("HttpService").HttpEnabled = true`
5. **Pair**: copy the token from the app, paste it into the Roickbot plugin panel in Studio,
and click **Connect**.
6. **Verify**: ask Claude to call the `health` tool — it should report `pluginConnected: true`.
Full steps: [docs/INSTALL.md](docs/INSTALL.md).
## Development
```bash
npm install
npm run build:core
npm test # unit tests
node smoke.mjs # end-to-end bridge smoke test (no Studio needed)
```
To run the desktop app from source you also need the Electron binary (run `npm install` **without**
`ELECTRON_SKIP_BINARY_DOWNLOAD`) and a built plugin:
```bash
npm run build:plugin # requires Rojo (see plugin/aftman.toml) -> dist/Roickbot.rbxmx
npm run build:desktop
npm start --workspace packages/desktop
```
## Available tools
**Phase 1 (core):** `health`, `get_tree`, `get_children`, `view_elements`, `get_properties`,
`set_properties`, `create_instance`, `delete_instance`, `clone_instance`, `reparent_instance`,
`get_script_source`, `set_script_source`, `get_selection`, `set_selection`.
**Run / test:** `start_test`, `stop_test`, `pause_test`, `get_run_state`, `get_console_output`.
**Phase 2 (make-graphics):** `build_parts`, `set_appearance`, `edit_terrain`, `set_lighting`,
`insert_decal`, `insert_model`, `build_gui`.
**Phase 3 (Bot vision & self-test):** `bot_spawn` (with `asPlayer` to tag it for player-based
systems), `bot_despawn`, `bot_move`, `bot_look`, `bot_state`, `bot_see`. While a test is running,
project-editing tools are locked (`RUNTIME_LOCKED`) — the run phase is read-only; reads, `bot_*`,
`run_luau`, `fire_signal` and `get_console_output` stay available.
**Runtime server agent & events:** `start_test` injects a server-context agent into the running game,
so `run_luau` gains `context:"server"` (real `IsServer()`/`IsRunning()`), `fire_signal` can trigger
server-side listeners (RemoteEvent/BindableEvent/ProximityPrompt/network ownership), and
`wait_for_event` blocks until the test's state changes instead of polling.
**Search, tags & surgical edits:** `edit_script_lines` (line-range edits), `find_instances`,
`search_by_property`, `search_scripts` (grep all script source) and `get_script_info` (inspect a
script "file" — class/lines/`Disabled`/`RunContext`/attributes), plus `get_tagged` / `get_tags` /
`add_tag` / `remove_tag`. `search_scripts` and `get_script_info` are read-only, so they work **while
the game is running** — built for debugging a live play-test.
**Project harness (cross-session memory):** `harness_init`, `harness_session_start`,
`harness_session_end`, `harness_status`, `harness_feature_update` — a persistent project memory
(metadata + features + session handoffs) handled locally by the app, so the AI remembers the project
across sessions even with Studio offline.
**Universal:** `run_luau`.
All mutating tools accept `dryRun: true` to preview without applying. There are **no artificial size
limits** — use `maxDepth` / `get_children` / `view_elements` filters to control payload size on
large projects. Full reference: [docs/TOOLS.md](docs/TOOLS.md).
## Use with other AI clients
It's a standard MCP server, so it works with any client that supports remote (HTTP) MCP servers
with custom headers — **not just Claude**. Point the client at `http://127.0.0.1:7331/mcp` with the
`Authorization: Bearer <token>` and `X-Roblox-MCP: 1` headers (the token is shown in the app).
**No manual editing needed:** pick your client (Claude Code, Cursor, Gemini CLI, Cline, VS Code) in
the app's dropdown and click **Install MCP config** — it writes the right `type`/key/path for that
client automatically (each one differs slightly, e.g. Cline needs `streamableHttp`, Gemini uses
`httpUrl`).
**Google Gemini (free tier)** — add to `~/.gemini/settings.json`:
```json
{
"mcpServers": {
"roickbot": {
"httpUrl": "http://127.0.0.1:7331/mcp",
"headers": { "Authorization": "Bearer PASTE_TOKEN", "X-Roblox-MCP": "1" }
}
}
}
```
Cursor, VS Code/Copilot, Cline + local Ollama (free), and other clients are covered — including
**free model options** — in **[docs/CLIENTS.md](docs/CLIENTS.md)**.
## Security
The bridge runs on your machine, so **any web page you open could try to reach `127.0.0.1`**. The
bridge defends against this with several independent checks on every request:
- **Loopback only** — binds `127.0.0.1`, never `0.0.0.0`.
- **Random Bearer token** — 256-bit, shown only in the native app, compared in constant time.
- **Studio-side pairing** — you paste the token into the plugin; a web page can never obtain it.
- **`Host` validation** — blocks DNS-rebinding.
- **`Origin` rejection** — any request with a browser `Origin` is refused.
- **Required custom header** — `X-Roblox-MCP: 1`, with no permissive CORS.
Details and threat model: [docs/SECURITY.md](docs/SECURITY.md).
## Roadmap
- **Phase 1 — core** ✅ scripts, instances, properties, selection, run/test, `run_luau`.
- **Phase 2 — make-graphics** ✅ `build_parts`, `set_appearance`, `edit_terrain`, `set_lighting`,
`insert_decal`, `insert_model`, `build_gui`.
- **Phase 3 — Bot vision & self-test loop** ✅ `bot_spawn/despawn/move/look/state`, `bot_see`
(structured, raycast-based perception); `start_test/stop_test/pause_test`; a runtime lock that
makes the project read-only while the game is running.
## License
MIT
<br>
---
---
<br>
## Development
```bash
npm install
npm run build:core
npm test # Unit test
node smoke.mjs # End-to-end bridge smoke test (no Studio required)
```
To run the desktop app from source, you also need the Electron binary (do not set
`ELECTRON_SKIP_BINARY_DOWNLOAD` when running `npm install`) and the built plugins:
```bash
npm run build:plugin # Requires Rojo (see plugin/aftman.toml) -> dist/Roickbot.rbxmx
npm run build:desktop
npm start --workspace packages/desktop
```
## Available Tools
**Phase 1 (Core):** `health`, `get_tree`, `get_children`, `view_elements`, `get_properties`,
`set_properties`, `create_instance`, `delete_instance`, `clone_instance`, `reparent_instance`,
`get_script_source`, `set_script_source`, `get_selection`, `set_selection`.
**Run / Test:** `start_test`, `stop_test`, `pause_test`, `get_run_state`, `get_console_output`.
**Phase 2 (Building):** `build_parts`, `set_appearance`, `edit_terrain`, `set_lighting`,
`insert_decal`, `insert_model`, `build_gui`.
**Phase 3 (Bot Vision + Self-Testing):** `bot_spawn` (with `asPlayer` for player-based systems),
`bot_despawn`, `bot_move`, `bot_look`, `bot_state`, `bot_see`. When the game is running, editing tools are locked
(`RUNTIME_LOCKED`) — read-only at runtime; `bot_*`, `run_luau`, `fire_signal`, `get_console_output` are still available.
**Runtime server agent + events:** `start_test` injects a server context agent into the running game, so
`run_luau` gets an extra `context:"server"` (proper `IsServer()`/`IsRunning()`), `fire_signal` can trigger server-side listeners
(RemoteEvent/BindableEvent/ProximityPrompt/network ownership), and `wait_for_event` can block on test state changes without polling.
**Search / Tags / Line Editing:** `edit_script_lines` (change scripts line-by-line), `find_instances`,
`search_by_property`, `search_scripts` (grep all script sources), `get_script_info` (view script "file" properties —
class name/line count/`Disabled`/`RunContext`/properties), and `get_tagged` / `get_tags` / `add_tag` / `remove_tag`.
`search_scripts` and `get_script_info` are read-only and **can be used even when the game is running** — designed for debugging running tests.
**Project harness (cross-session memory):** `harness_init`, `harness_session_start`, `harness_session_end`,
`harness_status`, `harness_feature_update` — application-maintained project memory (metadata + features + session handover),
allowing AI to remember project progress across sessions even if Studio isn't connected.
**Omnipotent:** `run_luau`.
All change tools support `dryRun: true` for preview-only changes. **No artificial size limits** — use
`maxDepth` / `get_children` / `view_elements` to control response volume on large projects. See [docs/TOOLS.md](docs/TOOLS.md) for the full reference.
## Use with Other AI Clients
This is a standard MCP server, **not just for Claude** — any client supporting "remote (HTTP) MCP + custom request headers" can be used. Point the client at `http://127.0.0.1:7331/mcp`, with `Authorization: Bearer <token>` and `X-Roblox-MCP: 1` (the token is in the app).
**No manual config required:** Under the app dropdown, select your client (Claude Code / Cursor / Gemini CLI / Cline / VS Code) and click **Install MCP config**, and the app will write the correct `type`/keys/paths for you (each has slight differences, e.g., Cline needs `streamableHttp`, Gemini uses `httpUrl`).
**Google Gemini (free tier)** — add to `~/.gemini/settings.json`:
```json
{
"mcpServers": {
"roickbot": {
"httpUrl": "http://127.0.0.1:7331/mcp",
"headers": { "Authorization": "Bearer paste-your-token", "X-Roblox-MCP": "1" }
}
}
}
```
See **[docs/CLIENTS.md](docs/CLIENTS.md)** for Cursor, VS Code/Copilot, Cline + local Ollama (free), and other **free model options**.
## Security
The bridge runs on your machine, so **any webpage you open may try to access `127.0.0.1`**. The bridge performs multiple independent checks to defend against this:
- **Binds only to loopback** — binds to `127.0.0.1`, never `0.0.0.0`.
- **Random Bearer token** — 256-bit, only shown in the native app, constant-time comparison.
- **Studio-side pairing** — you paste the token into the plugin; webpages can never get it.
- **Host validation** — prevents DNS-rebinding attacks.
- **Rejects `Origin`** — any request with a browser `Origin` header is rejected.
- **Requires custom headers** — `X-Roblox-MCP: 1`, with strict CORS.
See [docs/SECURITY.md](docs/SECURITY.md) for details and the threat model.
## Thoughtful Design
Beyond auth, the tools themselves are designed to be **cautious with Claude and non-disruptive**. Destructive operations return a dry-run preview and a one-time confirmation token (Claude must call again to actually execute); every change is a waypoint that can be Ctrl+Z-ed; Core services
(`CoreGui`, `CorePackages`, …) are never modifiable.
## Roadmap
- **Phase 1 — Core** ✅ Scripts, instances, properties, selection, run/test, `run_luau`.
- **Phase 2 — Building** ✅ `build_parts`, `set_appearance`, `edit_terrain`, `set_lighting`,
`insert_decal`, `insert_model`, `build_gui`.
- **Phase 3 — Bot Vision + Self-Testing Loop** ✅ `bot_spawn/despawn/move/look/state`, `bot_see` (ray-based structured perception); `start_test/stop_test/pause_test`; runtime lock (read-only projects while running).
## Licensing
MIT
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available