Roblox Studio MCP
README.md
<div align="center">
# 🎮 Roblox Studio MCP
### Give your AI full access to Roblox Studio
[](https://www.npmjs.com/package/@aaronalm19/roblox-mcp)
[](LICENSE)
[](https://nodejs.org)
[](https://www.typescriptlang.org/)
**Claude** · **Gemini** · **Codex** · **OpenCode** · *any MCP client*
[Quick Start](#-quick-start) · [Studio CLI](#-the-studio-cli) · [Features](#-features) · [Tools](#-tool-reference) · [Client Setup](#-client-setup) · [Docs](#-docs)
</div>
---
An [MCP](https://modelcontextprotocol.io/) server that connects AI assistants directly to a running Roblox Studio session. Read the instance tree, edit Luau scripts, set properties, manage attributes & tags, create objects, detect drift, and sync source files — all over a **100% local** connection that never leaves your machine.
```
Your AI MCP Server Studio Plugin
┌──────────┐ stdio ┌──────────────┐ HTTP ┌──────────────┐
│ Claude │◄──────────►│ Node.js │◄─────────►│ Luau │
│ Gemini │ │ port 3002 │ localhost │ polls every │
│ Codex │ │ │ │ 500ms │
└──────────┘ └──────┬───────┘ └──────────────┘
│
┌──────┴───────┐
│ Blueprint V1 │
│ Rojo sync │
└──────────────┘
```
---
> ## 🤖 Using an AI Agent? (Claude Code, Cursor, etc.)
>
> **Let your AI agent set everything up for you!**
>
> ### Option 1: Copy-Paste This Prompt
>
> Just copy and paste this to your AI agent:
>
> ```
> Go to https://raw.githubusercontent.com/aaronaalmendarez/roblox-mcp/main/AGENT.md
> Read the entire file, then set up the Roblox Studio MCP on my machine. Follow all the installation steps in the "Complete Installation Guide" section.
> ```
>
> Your agent will handle cloning, building, configuring MCP, and setting up Blueprint V1 automatically.
>
> ### Option 2: Manual
>
> - **[📖 View AGENT.md on GitHub](https://github.com/aaronaalmendarez/roblox-mcp/blob/main/AGENT.md)**
> - **[📋 View Raw](https://raw.githubusercontent.com/aaronaalmendarez/roblox-mcp/main/AGENT.md)** (copy all)
---
## 🚀 Quick Start
**1 →** Install the Studio plugin ([download `.rbxmx`](https://github.com/aaronaalmendarez/roblox-mcp/releases/latest/download/MCPPlugin.rbxmx)) into your plugins folder
| OS | Path |
| :------ | :------------------------------- |
| Windows | `%LOCALAPPDATA%\Roblox\Plugins\` |
| macOS | `~/Documents/Roblox/Plugins/` |
**2 →** In Studio: **Game Settings → Security → Allow HTTP Requests** ✅
**3 →** Start the server:
```bash
# From this repo
npm install && npm run build
node dist/index.js
```
**4 →** Configure your AI client (see [Client Setup](#-client-setup)) — done!
<details>
<summary><b>Build plugin from source</b></summary>
```bash
npm run build:plugin
# Copy studio-plugin/MCPPlugin.rbxmx → plugins folder → restart Studio
```
</details>
---
## ✨ Features
### 37+ MCP Tools
| | Category | What You Can Do |
| :--- | :--------------------- | :---------------------------------------------------------------- |
| 📂 | **Instance Hierarchy** | Browse game tree, search by name / class / content, list services |
| 📝 | **Script Management** | Read, write, line-edit Luau scripts with range support |
| ⚡ | **Batch Editing** | Atomic multi-op edits with SHA-256 hash checks + auto-rollback |
| 🔩 | **Properties** | Get/set any property, mass ops, formula & relative calculations |
| 🏗️ | **Object Lifecycle** | Create, delete, smart-duplicate with offset grids & variations |
| 🏷️ | **Attributes & Tags** | Full CRUD for attributes + CollectionService tags |
| 🩺 | **Diagnostics** | Drift detection, deprecated API lint, health endpoints, telemetry |
| 💾 | **Snapshots** | In-memory script snapshots with instant rollback |
### IDE-First Sync
- **Blueprint V1** — [Rojo](https://rojo.space/)-based multi-place source control
- **Bi-directional** — push local files to Studio *or* pull Studio changes back
- **Conflict-safe** — hash-based guards prevent accidental overwrites
- **Drift detection** — know exactly when local and Studio have diverged
### Built for Reliability
- Optimistic concurrency via SHA-256 source hashes
- Write idempotency — replay-safe with `X-Idempotency-Key`
- Chunked script uploads for very large rewrites that exceed single MCP payload limits
- Safe bridge fallback for script writes instead of `set_property` on `Source`
- Full-source reads for large scripts automatically avoid truncated plugin responses
- Smart plugin polling: hot → active → idle intervals
- Drift checks ignore formatting-only differences by default and report both raw and normalized hashes
- Atomic **apply → verify → rollback** pipeline
---
## 🎨 The Studio CLI
One command to rule them all. A zero-dependency, cross-terminal orchestrator for your entire Roblox workflow.
```
____ ____ ____________ ______________ _____
/ __ \/ __ )/ ____/ __ \/ _/ ____/ __ \/ ___/
/ /_/ / __ / / / / / // // / / / / /\__ \
/ _, _/ /_/ / /___/ /_/ // // /___/ /_/ /___/ /
/_/ |_/_____/\____/_____/___/\____/_____//____/
```
```bash
# One command starts everything
npm run studio -- dev
# Or pick your services
npm run studio -- mcp # MCP server only
npm run studio -- serve # Rojo server only
npm run studio -- dev --verbose # See all process output
```
### What it does
| Feature | Description |
| :------ | :---------- |
| **Process Orchestration** | Spawns MCP + Rojo + Watchers + Reverse Sync with a single command |
| **PID Tracking** | Every process gets a PID file in `.studio-cli/pids/` — no orphaned `node.exe` processes |
| **Cross-Platform Kill** | `taskkill /T` on Windows, `SIGTERM` on Unix — tree-wide shutdown, no zombies |
| **Log Capture** | Background processes write timestamped logs to `.studio-cli/logs/` |
| **Health Checks** | Auto-verifies MCP (HTTP) and Rojo (TCP socket) before reporting "ready" |
| **Place Context** | Auto-resolves active place, detected Studio place, or legacy fallback |
| **Beautiful UI** | ANSI boxes, spinners, tables, and status indicators — works in any terminal |
### Commands
```bash
studio dev # Full environment (MCP + Rojo + Watch + Reverse)
studio serve # Rojo server only
studio mcp # MCP server only
studio sync # Blueprint property sync once
studio watch # Property file watcher
studio build # Build .rbxl via Rojo
studio lint # Luau lint
studio place list # Places table with active marker
studio place status # Resolved context box
studio place use <key> # Switch active place
studio place detect # Auto-register current Studio place
studio status # System dashboard with health checks
studio stop [name] # Kill tracked process(es)
studio transcribe # Whisper transcription
studio doctor # Blueprint doctor
studio version # Version + logo
```
### Global Flags
```bash
--place <key> # Target place (slug / id / name)
--verbose # Show process output
--json # Machine-readable output
--dry-run # Preview changes without applying
```
---
## 🆕 Recent Reliability Fixes
- **Large script reads are no longer silently truncated** — full-source reads now return the complete script even when the plugin would otherwise cap the response to the first 1000 lines.
- **Formatting-only drift no longer shows up as content drift** — `check_script_drift` now normalizes line endings, BOM, trailing whitespace, and trailing final newlines by default.
- **Drift output is more explicit** — diagnostics now include `comparisonMode`, `formattingOnly`, `formattingDifferences`, raw hashes/lengths, and normalized hashes/lengths.
- **Large script writes now have a safe transport** — use the chunked upload tools or `scripts/push-script-fast.mjs` for large files; they commit through the plugin bridge and `UpdateSourceAsync` instead of `set_property`.
- **`Source` writes no longer go through property tools** — `set_property` and `mass_set_property` now reject the `Source` property so escape sequences are not corrupted.
- **Server and plugin defaults are aligned around port `3002`** — current builds start on `3002` first and keep `58741` only as a legacy fallback.
Example of the expected healthy case:
```json
{
"status": "in-sync",
"comparisonMode": "canonical-text",
"formattingOnly": true,
"formattingDifferences": ["trailing-newline"],
"rawLocalLength": 74884,
"rawStudioLength": 74883,
"normalizedLocalLength": 74883,
"normalizedStudioLength": 74883
}
```
This means the raw bytes differ, but the actual script content is the same.
A real healthy verification case now looks like this:
- Full source read: `localLength: 74883`, `studioLength: 74883`
- Raw bytes can still differ by one trailing newline: `rawLocalLength: 74884`, `rawStudioLength: 74883`
- Normalized hashes then match, so the result is correctly reported as `in-sync`
- The result includes `comparisonMode`, `formattingOnly`, `formattingDifferences`, and raw vs normalized hashes/lengths
---
## 🔧 Tool Reference
<details>
<summary><b>📂 Instance Hierarchy</b> — 9 tools</summary>
| Tool | Description |
| :---------------------- | :--------------------------------------- |
| `get_file_tree` | Instance hierarchy as a tree |
| `search_files` | Search by name, class, or script content |
| `get_services` | List Roblox services and children |
| `search_objects` | Find by name, class, or property |
| `get_project_structure` | Full game hierarchy (configurable depth) |
| `get_instance_children` | Children + class types |
| `get_class_info` | Properties/methods for any class |
| `get_place_info` | Place ID, name, game settings |
| `get_selection` | Currently selected objects |
</details>
<details>
<summary><b>📝 Script Management</b> — 15 tools</summary>
| Tool | Description |
| :------------------------------- | :--------------------------------- |
| `get_script_source` | Read source (optional line range, full reads safe for large scripts) |
| `get_script_snapshot` | Source + SHA-256 hash with full-source recovery |
| `set_script_source` | Full rewrite (editor-safe; use chunked upload for very large files) |
| `begin_script_source_upload` | Start chunked upload session for large files |
| `append_script_source_upload_chunk` | Append one chunk to an upload session |
| `commit_script_source_upload` | Commit an uploaded script through the plugin bridge |
| `cancel_script_source_upload` | Discard an upload session without writing |
| `set_script_source_checked` | Write only if hash matches |
| `set_script_source_fast` | Fast write with safe bridge fallback |
| `set_script_source_fast_gzip` | Gzip-compressed fast write |
| `edit_script_lines` | Replace line ranges |
| `insert_script_lines` | Insert at position |
| `delete_script_lines` | Delete line ranges |
| `batch_script_edits` | Atomic multi-edit + rollback |
| `apply_and_verify_script_source` | Apply → verify → rollback pipeline |
</details>
<details>
<summary><b>💾 Snapshots & Safety</b> — 4 tools</summary>
| Tool | Description |
| :------------------------- | :----------------------- |
| `create_script_snapshot` | In-memory rollback point |
| `list_script_snapshots` | List session snapshots |
| `rollback_script_snapshot` | Restore from snapshot |
| `cancel_pending_writes` | Cancel queued writes |
</details>
<details>
<summary><b>🔩 Properties & Objects</b> — 14 tools</summary>
| Tool | Description |
| :------------------------------------ | :---------------------------------- |
| `get_instance_properties` | All properties of an instance |
| `set_property` | Set any property except `Source` |
| `mass_set_property` | Set on multiple instances except `Source` |
| `mass_get_property` | Read from multiple instances |
| `search_by_property` | Find by property value |
| `set_calculated_property` | Formula-based property sets |
| `set_relative_property` | Relative modifications |
| `create_object` | Create instance |
| `create_object_with_properties` | Create with initial props |
| `mass_create_objects` | Batch create |
| `mass_create_objects_with_properties` | Batch create with props |
| `delete_object` | Delete instance |
| `smart_duplicate` | Smart dup with offsets & variations |
| `mass_duplicate` | Multiple smart dups at once |
</details>
<details>
<summary><b>🏷️ Attributes & Tags</b> — 7 tools</summary>
| Tool | Description |
| :-------------------------------- | :-------------------------- |
| `get_attribute` / `set_attribute` | Read/write single attribute |
| `get_attributes` | All attributes on instance |
| `delete_attribute` | Remove attribute |
| `get_tags` | CollectionService tags |
| `add_tag` / `remove_tag` | Add or remove tag |
| `get_tagged` | All instances with a tag |
</details>
<details>
<summary><b>🩺 Diagnostics</b> — 4 tools</summary>
| Tool | Description |
| :--------------------- | :------------------------------ |
| `get_runtime_state` | Write queue + bridge telemetry |
| `get_diagnostics` | Full diagnostic report |
| `check_script_drift` | Local vs Studio drift check with formatting normalization and raw/normalized diagnostics |
| `lint_deprecated_apis` | Deprecated API scanner |
</details>
---
## 🔌 Client Setup
> All configs point to the **local build**. Replace the path with your actual install location.
<details open>
<summary><b>Claude Code</b></summary>
```bash
claude mcp add robloxstudio -- node /path/to/roblox-mcp/dist/index.js
```
</details>
<details>
<summary><b>Gemini CLI</b></summary>
```bash
gemini mcp add robloxstudio node --trust -- /path/to/roblox-mcp/dist/index.js
```
</details>
<details>
<summary><b>Claude Desktop / Generic JSON</b></summary>
```json
{
"mcpServers": {
"robloxstudio-mcp": {
"command": "node",
"args": ["/path/to/roblox-mcp/dist/index.js"]
}
}
}
```
</details>
<details>
<summary><b>Codex CLI</b></summary>
`~/.codex/config.toml`:
```toml
[mcp_servers.robloxstudio]
command = "node"
args = ["/path/to/roblox-mcp/dist/index.js"]
```
</details>
<details>
<summary><b>OpenCode</b></summary>
`~/.config/opencode/opencode.json`:
```json
{
"mcp": {
"robloxstudio": {
"type": "local",
"enabled": true,
"command": ["node", "/path/to/roblox-mcp/dist/index.js"]
}
}
}
```
</details>
<details>
<summary><b>Published npm package</b></summary>
If using the published package instead of a local build:
```bash
npx -y @aaronalm19/roblox-mcp@latest
```
</details>
> **Full reference with Windows fallbacks:** [docs/CLIENTS.md](docs/CLIENTS.md)
---
## 📘 Blueprint V1
IDE-first source control built on [Rojo](https://rojo.space/) with multi-place support.
```
blueprint-v1/
├── places/
│ ├── registry.json # Place ID → slug
│ ├── .active-place.json # Active context
│ └── <slug>/
│ ├── default.project.json
│ ├── src/ # Luau source
│ └── properties/
│ └── instances.json # Non-script props
└── src/ # Legacy fallback
```
```bash
npm run place:detect # Auto-detect Studio place
npm run place:list # List registered places
npm run blueprint:sync # Property sync → Studio
npm run blueprint:watch # Continuous sync
npm run blueprint:reverse-sync # Pull Studio → local
npm run drift:check # Detect file divergence
npm run luau:lint # Static analysis (requires luau-lsp, see below)
```
### Luau Lint Setup (luau-lsp)
`npm run luau:lint` uses [luau-lsp](https://github.com/JohnnyMorganz/luau-lsp) which ships **full Roblox type stubs** — `Player`, `BasePart`, `Vector3`, `RemoteEvent`, etc. all resolve correctly under `--!strict`.
**One-time setup:**
Option A — use the bundled binary (already in this repo, v1.63.0 Windows x64):
```powershell
Expand-Archive tools\luau-lsp\luau-lsp-win64.zip -DestinationPath .tools\luau-lsp -Force
```
Option B — download the latest release for your platform:
- 👉 https://github.com/JohnnyMorganz/luau-lsp/releases/latest
- Download `luau-lsp-win64.zip` (Windows), `luau-lsp-macos.zip` (macOS), or `luau-lsp-linux.zip` (Linux)
- Extract `luau-lsp[.exe]` → `.tools/luau-lsp/luau-lsp.exe`
Then generate the Rojo sourcemap:
```bash
rojo sourcemap blueprint-v1/places/<slug>/default.project.json --output sourcemap.json
```
**Run:**
```bash
npm run luau:lint # findings=0 is the goal
npm run luau:lint:strict # exits non-zero if any findings (use in CI)
```
**Expected clean output:**
```
[context] Place1 (125175608517936) [place1-2]
[luau-lint] files=4 analyzer=.tools/luau-lsp/luau-lsp.exe
[luau-lint] sourcemap=sourcemap.json
[luau-lint] findings=0
```
> **Deep dive:** [docs/BLUEPRINT_V1.md](docs/BLUEPRINT_V1.md)
---
## 📋 Blueprint Operator Playbook
Everything below is the **strict operational guide** for working with Blueprint V1. Follow these steps exactly.
### 1. Canonical Windows Flow (copy-paste)
Open a terminal in the repo root and run each step in order:
```powershell
# Step 1 — Detect the place open in Studio and register it
npm run place:detect
# Step 2 — Confirm resolved paths
npm run place:status
# Step 3 — Start Rojo against the resolved project
rojo serve blueprint-v1/places/<slug>/default.project.json
# Step 4 — Start continuous property sync (separate terminal)
npm run blueprint:watch
# Step 5 — Start reverse sync guard (separate terminal)
npm run blueprint:reverse-sync
```
Or use the **one-command launcher** that does steps 3-5 automatically:
```powershell
npm run studio -- dev --place <slug>
```
Or the legacy orchestrator:
```powershell
npm run dev:studio -- --place <slug>
```
> This resolves the existing place context, then spawns the MCP server, Rojo, property watcher, and reverse-sync in parallel. It does **not** run `place:detect` — you must register the place first. Press `Ctrl+C` to stop all.
---
### 2. Required Tooling Install Matrix
| Tool | Required | Install (Windows) |
| :--------------- | :---------------------- | :------------------------------------------------------------------------------------------------------------ |
| **Node.js** ≥ 18 | ✅ Yes | `winget install OpenJS.NodeJS.LTS` or [nodejs.org](https://nodejs.org) |
| **Rojo** | ✅ Yes (for script sync) | `cargo install rojo` — or [download binary](https://github.com/rojo-rbx/rojo/releases) and add to `PATH` |
| **Luau CLI** | Optional (for lint) | `npm run luau:install` (auto-downloads from [luau-lang releases](https://github.com/luau-lang/luau/releases)) |
<details>
<summary><b>No winget or cargo?</b></summary>
- **Node.js:** Download the `.msi` installer from [nodejs.org/en/download](https://nodejs.org/en/download)
- **Rojo:** Download `rojo.exe` from [GitHub releases](https://github.com/rojo-rbx/rojo/releases), place in a folder on your `PATH`
- **Luau:** `npm run luau:install` handles this — it downloads the correct binary for your OS into `.tools/`
</details>
---
### 3. Expected Success Output Per Step
**`npm run place:detect`**
```
✔ Detected place: Place2 (136131439760483)
✔ Registered slug: place2
✔ Set as active place
```
**`npm run place:status`**
```
Mode: place
Place: Place2 (136131439760483)
Slug: place2
Project: blueprint-v1/places/place2/default.project.json
Source: blueprint-v1/places/place2/src
Properties: blueprint-v1/places/place2/properties/instances.json
```
**`rojo serve ...`**
```
Rojo server listening on port 34872
```
**`http://localhost:3002/health`**
```json
{
"pluginConnected": true,
"mcpServerActive": true,
"plugin": { "version": "1.10.0" }
}
```
**`npm run blueprint:reverse-sync`**
```
Reverse sync active. Tracked scripts: 3
Polling every 2000ms...
```
> If any output differs from the above, stop and consult the [Troubleshooting](#-troubleshooting) table.
---
### 4. Source of Truth Rules
| Situation | Who Wins | Action |
| :---------------------------------------------- | :--------------------- | :------------------------------------------------------------ |
| You edited a `.luau` file locally | **Local wins** | Rojo pushes to Studio automatically |
| You edited a script inside Studio | **Studio wins** | Run `npm run blueprint:reverse-sync` to pull changes back |
| Both sides changed the same script | **Neither** — conflict | A conflict snapshot folder is written; you manually merge |
| Non-script property changed in Studio | **Studio wins** | No automated pull — manually update `instances.json` to match |
| Non-script property changed in `instances.json` | **Local wins** | Run `npm run blueprint:sync` to push to Studio |
| You aren't sure what changed | **Check first** | Run `npm run drift:check` to compare hashes |
**Golden rule:** Edit scripts in your IDE (Rojo syncs them). Edit non-script properties via `instances.json`. Only reverse-sync when you intentionally made Studio-side script changes.
---
### 5. File Naming & Path Mapping
Rojo uses file suffixes to determine the script type and instance name:
| File Suffix | Script Type | Instance Name |
| :------------------ | :----------------------------- | :---------------------- |
| `.server.luau` | `Script` (runs on server) | Filename without suffix |
| `.client.luau` | `LocalScript` (runs on client) | Filename without suffix |
| `.module.luau` | `ModuleScript` (shared) | Filename without suffix |
| `.luau` (no suffix) | `ModuleScript` | Full filename |
**Path resolution example:**
```
File: blueprint-v1/places/place2/src/ServerScriptService/HorrorMain.server.luau
Instance: game.ServerScriptService.HorrorMain (Script)
File: blueprint-v1/places/place2/src/StarterPlayer/StarterPlayerScripts/HorrorClient.client.luau
Instance: game.StarterPlayer.StarterPlayerScripts.HorrorClient (LocalScript)
File: blueprint-v1/places/place2/src/ReplicatedStorage/HorrorConfig.module.luau
Instance: game.ReplicatedStorage.HorrorConfig (ModuleScript)
```
> The directory path under `src/` maps directly to the Roblox service hierarchy. The `default.project.json` defines which directories map to which services.
---
### 6. Conflict Handling
When reverse-sync detects **both local and Studio changed** the same script, it writes a conflict snapshot folder instead of overwriting:
```
blueprint-v1/places/<slug>/.reverse-sync-conflicts/
└── ServerScriptService/
└── HorrorMain.server.luau/
├── local.luau # Your local version at time of conflict
├── studio.luau # The Studio version that diverged
└── meta.json # Timestamps, hashes, instance path
```
**Recovery workflow:**
1. Open the conflict folder (e.g. `.reverse-sync-conflicts/ServerScriptService/HorrorMain.server.luau/`)
2. Compare `local.luau` (your version) vs `studio.luau` (Studio's version)
3. Manually merge the changes into the original `.luau` file in `src/`
4. Delete the conflict folder
5. Run `npm run blueprint:reverse-sync` again — it will re-baseline from the merged file
**State tracking:** Each tracked script's hashes are stored in:
```
blueprint-v1/places/<slug>/.reverse-sync-state.json
```
This file contains `lastLocalHash` and `lastStudioHash` per script. If you need to force a full re-sync, delete this file and restart reverse-sync.
---
### 7. Common Failures & Fixes
| Failure | Cause | Fix |
| :--------------------------------- | :------------------------------------------ | :---------------------------------------------------- |
| Place resolves wrong slug | `.active-place.json` points to old place | `npm run place:detect` (re-detects from Studio) |
| `rojo: command not found` | Rojo not installed or not on PATH | Install via `cargo install rojo` or download binary |
| Module path mismatch | File in wrong `src/` subdirectory | Match directory to Roblox service name exactly |
| HTTP 403 from plugin | HTTP requests disabled in Studio | Game Settings → Security → Allow HTTP Requests |
| Stale `.active-place.json` | Switched Studio places without re-detecting | `npm run place:detect` |
| `ECONNREFUSED :3002` | MCP server not running | `npm run studio -- dev` or `npm run dev:studio` |
| Reverse-sync shows 0 tracked | No scripts match Rojo mappings | Verify files exist in resolved `src/` path |
| Rojo sync not updating Studio | Rojo serving wrong project file | Check `npm run place:status` for correct project path |
| Lint says "luau-analyze not found" | Luau CLI not installed | `npm run luau:install` |
| `blueprint:doctor` fails | Server or plugin not connected | Start server, open Studio, enable plugin |
---
### 8. One-Command Dev Launcher
The **Studio CLI** is the recommended daily driver:
```powershell
npm run studio -- dev --place place2
```
Or use the legacy orchestrator:
```powershell
npm run dev:studio -- --place place2
```
Both start **all four services** in parallel:
| Service | What It Does |
| :------------------- | :----------------------------------------------------------- |
| **MCP server** | `node dist/index.js` |
| **Rojo** | `rojo serve blueprint-v1/places/place2/default.project.json` |
| **Property watcher** | Continuous `blueprint:watch` for non-script sync |
| **Reverse sync** | Guarded Studio → local pull |
The CLI adds PID tracking, health checks, log capture, and a beautiful terminal UI:
```
✓ Resolved: Place2 [place2]
✓ MCP server listening on port 3002
✓ Rojo server listening on port 34872
✓ Property watcher active
✓ Reverse sync active
┌─────────────────────────────────────────────────────────────────────────┐
│ Dev Environment │
│ Project: blueprint-v1\places\place2\default.project.json │
│ Mode: place │
│ Studio: ● Press Ctrl+C to stop all │
└─────────────────────────────────────────────────────────────────────────┘
```
> **CLI flags:** `--no-rojo`, `--no-watch`, `--no-reverse` to disable individual services. `--verbose` to see process output.
---
### 9. Blueprint Scope Boundaries
Blueprint separates concerns cleanly between two systems:
| What | Managed By | Files |
| :------------------------------------------------------ | :------------------------------------ | :------------------------------------------------------- |
| **Scripts** (Luau code) | **Rojo** | `.server.luau`, `.client.luau`, `.module.luau` in `src/` |
| **Non-script properties** (Position, Size, Color, etc.) | **Sync scripts** | `properties/instances.json` |
| **Attributes** | **Sync scripts** | `properties/instances.json` (attributes field) |
| **Tags** | **Sync scripts** | `properties/instances.json` (tags field) |
| **Instance creation / hierarchy** | **Rojo** (via `default.project.json`) | `default.project.json` tree |
**Do NOT:**
- Edit `.luau` files through `instances.json` — Rojo handles scripts
- Create new services by adding directories without updating `default.project.json`
- Mix legacy `blueprint-v1/src/` with place-specific `blueprint-v1/places/<slug>/src/`
---
### 10. Example: Horror Game (`place2`)
A complete real-world place from this repository:
```
blueprint-v1/places/place2/
├── default.project.json # Rojo project mapping 12 services
├── .reverse-sync-state.json # Tracks 3 scripts with SHA-256 hashes
├── .reverse-sync-conflicts/ # Empty (no conflicts currently)
├── src/
│ ├── ServerScriptService/
│ │ └── HorrorMain.server.luau # → game.ServerScriptService.HorrorMain (Script)
│ ├── ReplicatedStorage/
│ │ └── HorrorConfig.module.luau # → game.ReplicatedStorage.HorrorConfig (ModuleScript)
│ └── StarterPlayer/
│ └── StarterPlayerScripts/
│ └── HorrorClient.client.luau # → game.StarterPlayer.StarterPlayerScripts.HorrorClient (LocalScript)
└── properties/
├── instances.json # Non-script property manifest (empty for now)
└── schema.json # Property schema definitions
```
**Registry entry** (`blueprint-v1/places/registry.json`):
```json
{
"136131439760483": {
"placeId": 136131439760483,
"gameId": 9708597637,
"slug": "place2",
"displayName": "Place2"
}
}
```
**Full workflow for this place:**
```powershell
# One-time: detect and register
npm run place:detect
# → ✔ Detected place: Place2 (136131439760483), slug: place2
# Daily: start everything
npm run studio -- dev --place place2
# → MCP server, Rojo, property watcher, and reverse sync all running
# Or the legacy orchestrator:
npm run dev:studio -- --place place2
# Or manually:
rojo serve blueprint-v1/places/place2/default.project.json
npm run blueprint:watch
npm run blueprint:reverse-sync
```
---
## 🛠️ Development
```bash
npm install # Dependencies
npm run build # TypeScript → dist/
npm run build:plugin # Build .rbxmx plugin
npm run dev # Dev server (tsx hot reload)
npm run typecheck # Type-check
npm test # Jest suite
npm run test:all # Jest + Luau E2E
```
### Verify Connection
```bash
curl http://localhost:3002/health
curl http://localhost:3002/diagnostics
```
### Project Layout
```
├── src/ # TypeScript MCP server
│ ├── index.ts # Tool definitions + handler
│ ├── http-server.ts # Express bridge (:3002)
│ ├── bridge-service.ts # Plugin comms
│ └── tools/ # Tool implementations
├── studio-plugin/ # Luau Studio plugin
├── blueprint-v1/ # Rojo projects + sync state
├── scripts/ # 20+ CLI helpers
├── tests/ # Jest + Luau E2E
└── docs/ # Additional docs
```
---
## 🔒 Security
| | |
| :--------------- | :----------------------------------------------- |
| **Local-only** | All traffic stays on `localhost:3002` |
| **No telemetry** | Zero data collection — your projects are private |
| **Explicit** | Tools only run when your AI invokes them |
| **Separated** | Read and write operations are distinct |
---
## ❓ Troubleshooting
| Problem | Fix |
| :------------- | :----------------------------------------------------- |
| Plugin missing | `.rbxmx` in plugins folder → restart Studio |
| HTTP 403 | Game Settings → Security → Allow HTTP Requests |
| Disconnected | Start the MCP server — red is normal until then |
| No tools | Restart MCP client + Studio, check `/health` |
| Slow or large writes | Use chunked upload tools or `push-script-fast.mjs` |
| Firewall | Allow `localhost:3002` |
---
## 📚 Docs
| | |
| :--------------------------------------------------- | :------------------------- |
| [Client Configurations](docs/CLIENTS.md) | Setup for every MCP client |
| [Blueprint V1 Guide](docs/BLUEPRINT_V1.md) | Multi-place sync deep dive |
| [Plugin Installation](studio-plugin/INSTALLATION.md) | Detailed plugin setup |
---
## 🤝 Contributing
```bash
git clone https://github.com/aaronaalmendarez/roblox-mcp.git
cd roblox-mcp
npm install
npm run dev
```
Issues and PRs welcome on [GitHub](https://github.com/aaronaalmendarez/roblox-mcp).
## 🙏 Acknowledgements
Original project: [`boshyxd/robloxstudio-mcp`](https://github.com/boshyxd/robloxstudio-mcp)
This fork extends that foundation for multi-agent workflows, local blueprint-first development, and enhanced tooling.
---
<div align="center">
**[MIT License](LICENSE)** © 2025
</div>
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues