
Studio Sidecar
io.github.gjlmotea由 GitHub 帳號 gjlmotea 發布v0.1.1更新於 Nov 2, 2026
Companion to Roblox Studio's built-in MCP: open places, guard writes, Open Cloud asset uploads.
概覽
Roblox Studio 的配套 MCP 伺服器,可開啟尚未開啟的場景、依 PlaceId 保護寫入、擷取腳本並透過 Open Cloud 上傳資源。
- 可以做什麼
- 檢視 Studio 程序與 StudioMCP broker,開啟尚未開啟的場景,並清理殘留的 stub
- 在強制 PlaceId 檢查下執行 Luau,執行期錯誤以可讀值回傳,並可在 100k 輸出上限之外以位元組比對擷取場景腳本
- 透過 Roblox Open Cloud 讀取、上傳、更新與封存資源,並在更新被去重時給出明確結論
- 回報狀態,包括 Open Cloud 是否已設定以及上傳可讀取哪些資料夾
- 適用情境
- 適合與 Roblox Studio 內建 MCP 伺服器搭配使用:需要開啟尚未執行的遊戲、避免誤覆蓋其他遊戲、匯出超過內建輸出上限的腳本快照,或透過 Open Cloud 管理資源時。腳本編輯、場景查詢、截圖與試玩刻意留給內建伺服器。
- 執行需求
- 以 npx 啟動的本機 stdio 程序,需要 Node.js 22 或更新版本,以及已開啟「Enable Studio as MCP server」的 Roblox Studio。選用環境變數:ROBLOX_API_KEY(具 Asset 讀寫權限的 Open Cloud 金鑰,僅四個 Open Cloud 工具需要)、ROBLOX_CREATOR_USER_ID、ROBLOX_UPLOAD_ROOT(未設定時拒絕所有上傳)與 ROBLOX_STUDIO_PATH。Windows 已完整驗證,macOS 部分驗證,Linux 會被明確拒絕。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Studio Sidecar,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
Studio Sidecar — companion MCP server for Roblox Studio
English | 繁體中文
[Studio Sidecar: a companion MCP server for Roblox Studio]
Studio Sidecar fills the gaps in Roblox Studio's built-in MCP server. It does not replace it.
Since 2026, Roblox Studio ships its own MCP server (StudioMCP, installed with Studio, stdio transport), and the standalone Roblox/studio-rust-mcp-server repository has been archived. The built-in server has tools that no third party can rebuild: generate_mesh, generate_material and generate_procedural_model use Roblox's cloud AI with moderation; search_asset, insert_asset and upload_image carry your signed-in inventory permissions; user_keyboard_input and user_mouse_input go through CreateVirtualInput. Replacing it would throw all of that away.
So Studio Sidecar adds only what the built-in server structurally cannot do, and leaves everything else to it:
- Open a place that is not open yet, and see every Studio process and StudioMCP broker/stub on the machine.
- Guard writes by PlaceId, run Luau with runtime errors returned as readable values and output never truncated, and extract scripts past the 100k output limit with byte-exact verification.
- Upload, update and archive assets through Roblox Open Cloud, with an explicit verdict when an update was silently deduplicated.
No Studio plugin is needed. 11 tools; Windows fully verified, macOS partly (see Platform support).
Contents
- Tools
- Quick start
- Configuration
- What the tools know that the built-in server does not tell you
- Platform support
- Boundaries
- Development
- License and trademarks
Tools
Deliberately not included: script reading and writing, scene queries, execute_luau, screen_capture, playtesting. The built-in server already has them, and a second implementation would only drift.
How Luau runs on the Studio side
An MCP process can be a server and a client at the same time. Studio Sidecar starts StudioMCP as its own child process and connects to it as an MCP client, which gives it the built-in execute_luau. The chunking, sentinel and byte-check machinery is then wrapped into single tools. When the client closes normally, the child process goes away too, so this route does not leak stubs.
To start StudioMCP, Studio Sidecar uses the same launcher as Roblox's setup guide. On Windows that is %LOCALAPPDATA%\Roblox\mcp.bat, run through cmd.exe /c; when mcp.bat is missing, it falls back to the most recently modified StudioMCP.exe under %LOCALAPPDATA%\Roblox\Versions\. On macOS it uses StudioMCP inside RobloxStudio.app, in /Applications or ~/Applications.
Quick start
Requirements: Roblox Studio with Enable Studio as MCP server turned on (in Studio: Assistant → … → Manage MCP Servers), and Node.js 22 or newer.
Register Studio Sidecar with your AI client. Claude Code:
Clients that read an mcpServers JSON config (Claude Desktop, Cursor, Gemini CLI):
VS Code uses a top-level servers key instead, and each server has a type. An input variable keeps the key out of the file: VS Code asks for it the first time the server starts and stores it securely.
Where each client keeps the file:
Sources: Claude Desktop, Cursor, Gemini CLI, VS Code.
All three variables are optional: without the key the four Open Cloud tools refuse, without ROBLOX_UPLOAD_ROOT every upload is refused, and the other tools work as usual. Do not put the key in any config file that is tracked by version control.
Register Studio's built-in MCP server as well; script editing, screenshots and playtesting live there. The launch command on each platform, StudioMCP on macOS and cmd.exe /c %LOCALAPPDATA%\Roblox\mcp.bat on Windows, comes from Roblox's setup guide.
macOS:
Windows:
In a JSON config, the macOS entry is "command": "/Applications/RobloxStudio.app/Contents/MacOS/StudioMCP", and the Windows entry is "command": "cmd.exe" with "args": ["/c", "%LOCALAPPDATA%\\Roblox\\mcp.bat"]. Register mcp.bat rather than StudioMCP.exe on Windows: mcp.bat keeps its path, while StudioMCP.exe lives in %LOCALAPPDATA%\Roblox\Versions\version-<hash>\, a folder that changes with Studio updates.
Restart the session after registering, then call roblox_get_status and check openCloudConfigured and allowedUploadRoots.
Desktop apps started from Finder or the Start menu often do not see your shell's PATH; if the server does not start, use the absolute path of npx (or of node when running from source).
Running from source
Register with absolute paths, as above, rather than a hand-written .mcp.json that points at the project folder. Claude Code sets CLAUDE_PROJECT_DIR in the server's environment, not in its own, so a ${CLAUDE_PROJECT_DIR} reference in the command or args of a .mcp.json entry, or of a local- or user-scope entry in ~/.claude.json, needs a default such as ${CLAUDE_PROJECT_DIR:-.}. Without a default the entry still loads, claude mcp list shows a missing-variable warning, and the unexpanded ${CLAUDE_PROJECT_DIR} text is used as is. Project-scope servers from .mcp.json also need approval: interactive sessions ask before using them, while claude -p runs, Agent SDK sessions and cloud sessions load them without asking. See the Claude Code MCP documentation.
Configuration
ROBLOX_UPLOAD_ROOT is a deliberate guard rail: uploading sends a local file to an external service, and for Models it cannot be undone, so the MCP client may not pick arbitrary file paths. Both the file and the allowed folders are resolved with realpath before they are compared, so a symlink inside an allowed folder cannot point the upload elsewhere. The file is opened once, checked again through that open handle (still inside an allowed folder, still the same file), and the bytes that go out are read from that handle, so swapping the path after the check changes nothing. A file with more than one hard link is refused, because a hard link inside an allowed folder can be a file from anywhere else on the same volume; upload a copy instead.
What the tools know that the built-in server does not tell you
Each of these was found on real hardware and has a regression test.
Launch intent quoting fails silently. Studio expects -launchIntentString "{\"task\":\"EditPlace\",\"universeid\":\"…\",\"placeid\":\"…\"}". Unescaped quotes are eaten by the Windows command-line parser, Studio receives broken JSON, ignores the intent and opens an empty session with no error. The only clue is a window title of Roblox Studio instead of <place name> - Roblox Studio. Studio Sidecar passes arguments to spawn as an array and makes the CommandLineToArgvW rules testable. universeid is the gameId in scene/place.json.
Never steal window focus. Two seconds after SetForegroundWindow, a stray key press in Studio closed the place that had just loaded. roblox_open_place only polls the broker connection and process titles.
The broker must not be killed, and its identity moves. StudioMCP is one broker plus one stub per client; the first one listens on 127.0.0.1:13469, and Studio itself and every stub connect to it. Killing the broker drops every connection, Studio's included. The broker role also moves to a different process over time, so the broker is always identified as "whoever listens on 13469", never by a remembered PID. roblox_cleanup_stubs gives up when it cannot identify the broker. Stubs pile up because some clients do not reap them on exit (see openai/codex#25893); an age threshold keeps cleanup away from sessions that may still be alive.
An update succeeds by revisionId, not by HTTP status. PATCHing an asset with byte-identical content returns HTTP 200, done: true and no error, but revisionId does not move: the content was deduplicated. roblox_update_asset compares revisionId before and after and reports updated, deduplicated or indeterminate. A higher revisionId still does not guarantee that Studio sees the new content; Studio-side caching is outside what Open Cloud can confirm. To replace content, do not send updateMask (updateMask=fileContent fails with Unknown field file_content); it is only for metadata changes.
The 100k truncation belongs to StudioMCP itself. Measured directly against StudioMCP: a 100,000-character reply arrives whole; a 120,000-character one stops at 100,015 characters ending in ... (truncated). No client can lift it. roblox_extract_place therefore uses three safeguards, all required:
- A sentinel at the end of every chunk; a chunk without it counts as incomplete. Length alone cannot tell a complete reply from a truncated one.
- The UTF-8-safe cut point is decided in Lua and reported back, and the caller continues from there, so the two sides never compute boundaries separately.
- A byte-count check per file (
Buffer.byteLength, notString.length). Any mismatch aborts the whole extraction, because a partially correct snapshot looks like success.
Each call stages its data under its own key, shared.RBXEXTRACT_<32 hex digits> (Lua VM memory only, never the DataModel or the .rbxl), and clears it afterwards, so overlapping calls never read each other's data. If clearing fails, the next call that reaches the same Studio clears it again, up to three attempts in all. Every key also records when it was last used, and each new key first clears any key that has sat idle for 15 minutes, so a key left behind by a failed release, a shutdown or a crash goes away on the next call to that Studio. During shutdown the server never reconnects to Studio just to clean up.
Instance names can be almost anything, including .., path separators and Windows device names such as CON or NUL, so every path segment is sanitized. A device name gets a trailing _ (CON becomes CON_.server.luau) on every platform, so a snapshot made on macOS still opens on Windows, and the final path is checked to be inside the output folder before writing.
The whole new snapshot is first written to a fresh folder that the extraction creates inside the output folder (.studio-sidecar-staging-<random>). Only after every file is there does the switch start: the files of the previous snapshot are moved aside, and the new ones are put in place with hard links that fail if the name is taken (or, on file systems without hard links, with exclusive creation). If anything fails during the switch, the new files are removed and the previous snapshot is moved back, so a failed run leaves the previous snapshot as it was. Extractions into the same folder run one after another. A run that is killed midway can leave a .studio-sidecar-staging-* folder behind; it holds only snapshot files and is safe to delete.
Nothing is ever overwritten. When a name is already taken, including by a name the file system treats as equal (Σ, ς and σ on a case-insensitive volume), the script gets the next ~n suffix, and scene/scripts.json records the path actually written. Re-running into the same folder replaces only the files listed in that folder's previous scene/scripts.json; a folder whose scene/ files were not written by Studio Sidecar is refused. If one of those files has been turned into a hard link, only that name is removed, and the content under the other name stays as it was.
The Studio bridge must live as long as the server. Closing it after every call makes the first call succeed and every later one fail with "Unable to reach Roblox Studio right now", which sounds like Studio is closed. It is not: closing kills the stub, and the next call races the broker. The same message also appears during a cold start before a fresh stub reaches the broker, so the bridge retries the Studio listing on that one message, and only that one, for up to 20 seconds; the wait grows by 250 ms per attempt, up to 1.5 seconds. Once the server starts shutting down, the bridge refuses new connections, so a call that is still finishing cannot start a fresh stub.
Open Cloud formats are narrow. Models accept .fbx only; Decals accept bmp, jpeg, png and tga; Audio accepts mp3 and ogg and can only be created, not updated, under a monthly quota. Wrong formats would only fail after polling the operation, so they are rejected locally. Models and Decals have never supported archiving, and roblox_archive_asset says so up front.
Platform support
Platform differences sit behind ports/process-inspector.ts; broker detection, stub classification and cleanup are shared. Linux is refused explicitly rather than returning an empty snapshot, because Roblox Studio does not run there and an empty answer would read as "no Studio running".
Boundaries
- No window focus changes. Stealing focus can make a stray key close a freshly loaded place.
roblox_luau_safeis not a new way to run arbitrary code.execute_luauis already in the client's hands; this tool adds a mandatory PlaceId guard, onepcallaround the whole chunk and chunked results in front of the same entry point. Thepcallcatches a runtime error and returns it as a readable value; the code after the error does not run, and changes made before the error are not rolled back. It is not a sandbox.- No reverse engineering of the broker's private protocol on 13469. Talking to
StudioMCPas an ordinary MCP client makes that unnecessary. - No "remove from inventory". That goes through
inventory.roblox.comwith a signed-in session cookie and CSRF token, which an Open Cloud API key cannot do. - Known limitation: a folder that already exists in the output folder can be swapped during the switch. Files are written into the fresh staging folder, but putting them in place still walks the output folder's existing sub-folders by path. Each level is resolved with
realpathand checked to be inside the output folder first; another program on the same machine could still replace a folder with a symlink between that check and the move (time-of-check/time-of-use). The move only ever creates a new name, so at worst one new file appears outside the output folder; nothing outside is overwritten or deleted. - Known limitation: an unreleased buffer lasts until the next call. A Luau buffer that could not be released stays in Studio's
sharedtable until a later call reaches the same Studio (and, for the idle sweep, until it has been idle for 15 minutes), or until Studio closes.
Development
verify:live only performs read-only operations: no uploads, updates, opened places or terminated processes. Its Open Cloud part needs ROBLOX_API_KEY and an asset ID (node scripts/verify-live.mjs <assetId>) and is skipped otherwise.
verify:extract needs ROBLOX_VERIFY_PLACE_ID, ROBLOX_VERIFY_UNIVERSE_ID (a place you own) and ROBLOX_VERIFY_BASELINE (a hand-made, byte-verified script snapshot). It opens a Studio instance and compares the extracted scripts byte for byte against the snapshot. The steps are chained on purpose, because the bridge lifetime bug only shows up across several consecutive tool calls.
License and trademarks
MIT.
Studio Sidecar is an independent open-source project, not affiliated with or endorsed by Roblox Corporation. Roblox, Roblox Studio and Luau are trademarks of Roblox Corporation.
來源:README.md,提交 eebeb8b
工具
0版本歷史
2- v0.1.1最新Oct 19, 2026
- v0.1.0Oct 18, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分