# Place management

romcp can open local or published places in Studio, download authorized place files, upload a file to an existing place, and manage supported Open Cloud settings. These operations do not need a connected Studio plugin. Opening a published place uses Studio's signed-in account; cloud operations use the key configured in romcp's control panel.

## MCP tools

| Tool                           | Input                                                                                                                             | Result                                             |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| `studio_open_place`            | Absolute `filePath`, **or** `universeId` + `placeId`; optional `versionNumber` for a published revision                           | Launch dispatched, `ready: false`                  |
| `roblox_download_place`        | `universeId`, `placeId`, new absolute `outputPath`; optional `versionNumber`                                                      | File path, byte count, SHA-256                     |
| `roblox_publish_place`         | `universeId`, `placeId`, absolute `filePath`, `versionType: "Saved"` or `"Published"`, `confirm: true`; optional `expectedSha256` | `uploaded`, `published`, version number, file hash |
| `roblox_read_place_settings`   | `universeId`; add `placeId` for place settings                                                                                    | Supported resource fields and `updateTime`         |
| `roblox_update_place_settings` | Same target, `changes`, `expectedUpdateTime`, `confirm: true`                                                                     | `updated`, `verified`, readback or explanation     |

Example requests to your AI:

- “Open `C:\Games\my-place.rbxl` in Studio.”
- “Open place 456 in universe 123, version 7.”
- “Download my place 456 in universe 123 to `/Users/me/Projects/backup.rbxl`.”
- “Publish this saved place file to place 456 in universe 123.”
- “Change that place's server size to 30.”

The IDs above are placeholders. Use the IDs of your actual experience and place.

## Studio launch

The launcher uses Roblox's documented `EditFile`, `EditPlace`, and `EditPlaceRevision` command-line tasks. Windows discovers Studio under `%LOCALAPPDATA%\Roblox\Versions`. macOS checks `/Applications/RobloxStudio.app` and `~/Applications/RobloxStudio.app`. For another installation, set `ROMCP_STUDIO_PATH` in the romcp process environment to the full Studio executable path.

Only `.rbxl` and `.rbxlx` files are accepted. The content header must match the extension; this checks the container signature, not every instance inside the file. Local opens are limited to 512 MiB. Launching does not establish that Studio signed in, loaded the place, or connected the plugin. Inspect `dominus_status`, match the requested place, and select that connection before editing. For local files with place ID zero, inspect the new session to distinguish it from other unsaved places. Existing sessions are not closed and romcp does not change the selected target.

## Downloads and publishing

Downloads use the authenticated Open Cloud asset-delivery endpoint. The key needs `legacy-asset:manage` and access to the requested place. Roblox enforces access; this is not a way to download private games you cannot edit. Group places may require a user-owned API key whose account has the necessary group permissions.

The destination's parent directory must exist. Downloads refuse to overwrite existing files, including a file created while the download is in progress. Data is streamed to a temporary file and checked before committing, with a 512 MiB limit. The `.rbxl` or `.rbxlx` extension must match the returned content. Only HTTPS Roblox CDN locations are followed; the Open Cloud key is never sent to the CDN or included in results.

Publishing requires `universe-places` Write access to the requested experience (`universe-places:write`). romcp verifies the place belongs to the requested universe before uploading. This implementation follows the 10 MiB size limit in Roblox's OpenAPI definition. It sends the contents of the specified file, not the live Studio DataModel or unsaved edits.

- `Saved`: `uploaded: true`, `published: false`, and a version number mean Roblox accepted a saved draft.
- `Published`: `uploaded: true`, `published: true`, and a version number mean Roblox accepted a published version. Existing servers are not restarted.
- `uploaded: false`: Roblox rejected the request.
- `uploaded: "unknown"`: the response was lost, invalid, or inconclusive. Inspect place version history in Creator Dashboard before retrying. romcp never automatically repeats the write.

`expectedSha256` can bind the upload to a previously reviewed file. A mismatch stops before any upload.

Roblox documents publishing limitations for EditableImage, EditableMesh, PartOperation, SurfaceAppearance, and BaseWrap content. Publish through Studio after modifying those types. These tools update existing places; creating a new experience/place and publishing the current unsaved Studio session are not included.

## Settings

With `placeId`, supported changes are `displayName`, `description`, and `serverSize` (1–200 in romcp). Updating the root place's name or description updates the experience's corresponding fields. Place writes require `universe.place:write`. Roblox can reject updates while Team Create is active with HTTP 409.

Without `placeId`, supported experience changes are `voiceChatEnabled`, `desktopEnabled`, `mobileEnabled`, `tabletEnabled`, `consoleEnabled`, `vrEnabled`, `privateServerPriceRobux`, and supported Facebook/Twitter/YouTube/Twitch/Discord/Roblox-group/Guilded social links. Social links use `{ title, uri }`; null removes a link. Experience writes require `universe:write`.

Changing private-server price cancels existing subscriptions. Setting the price to null disables active private servers. Zero enables free private servers. Visibility, age rating, and other read-only fields are not writable through these contracts.

Read settings first and pass the returned `updateTime` as `expectedUpdateTime`. romcp rereads before writing and returns `updated: false` if it differs. Only supplied fields enter the update mask. The comparison is a preflight check, not a server-side atomic lock; avoid concurrent edits. After acceptance, romcp reads back the fields and reports `verified` and any `mismatches`. A successful HTTP/MCP envelope alone does not prove a setting changed.

## Public SDK and HTTP API

All five methods also have authenticated POST routes under `/v1/places/`: `open`, `download`, `publish`, `readSettings`, and `updateSettings`. Paths refer to files on the machine running romcp. No file bytes, API keys, or signed CDN URLs are returned through these endpoints.

```ts
import { createClient } from 'dominus-cli/sdk';

const client = createClient({
  baseUrl: 'http://127.0.0.1:18090/v1',
  token: process.env.ROMCP_API_TOKEN!,
});

await client.places.open({ filePath: '/Users/me/Projects/my-place.rbxl' });

const current = await client.places.readSettings({ universeId: 123, placeId: 456 });
if (current.resource.updateTime) {
  const result = await client.places.updateSettings({
    universeId: 123,
    placeId: 456,
    expectedUpdateTime: current.resource.updateTime,
    changes: { serverSize: 30 },
    confirm: true,
  });
  console.log(result.updated, result.verified);
}
```

The SDK defaults to 120 seconds for downloads and 90 seconds for publishing; an explicit `timeoutMs` overrides these defaults. Timing out the caller does not cancel an already-dispatched publish. Downloads spend at most 30 seconds per metadata request and 90 seconds on CDN content. Their total time can exceed the SDK deadline; check the destination before retrying after a timeout.

## Sources and validation

- [Studio command-line interface](https://create.roblox.com/docs/studio/command-line-interface)
- [Place publishing guide](https://create.roblox.com/docs/cloud/guides/usage-place-publishing)
- [Universes and place settings](https://create.roblox.com/docs/cloud/reference/features/universes)
- [Asset delivery announcement](https://devforum.roblox.com/t/creator-action-required-new-asset-delivery-api-endpoints-for-community-tools/3574403)
- [Roblox OpenAPI definition](https://github.com/Roblox/creator-docs/blob/main/content/en-us/reference/cloud/openapi.json)

Tests exercise MCP registration, local HTTP/SDK routing, Windows/macOS executable discovery, launch arguments, file validation, download cleanup, exact publishing bytes, settings readback, and failed/uncertain writes using simulated Roblox responses. They do not establish live Open Cloud permissions or successful publication to a production game.

On 2026-10-09, a local empty `.rbxlx` launched in Windows Studio and connected to the romcp bridge without changing the active target. A live settings read also succeeded. The configured key returned HTTP 403 for asset delivery, so a live place download could not be verified with that key. Live publishing/settings writes and macOS launching have not been exercised.
