This is a reference for the .studiomcbc extension format used by mcbCode Studio
(studio.mcbcode.com). It describes what is actually implemented right now, not
where the format is eventually headed — anything declared-but-not-enforced is
called out explicitly so you don't build against a feature that doesn't run yet.
A .studiomcbc file is plain JSON with exactly two top-level keys:
{
"manifest": { ... },
"code": "// raw javascript, as a single string"
}manifest— metadata + permission declarations (see section 2).code— the extension's actual JavaScript source, as one string. This runs inside a sandboxed<iframe sandbox="allow-scripts">with no access to the main page's DOM, cookies, or storage. The only way in or out is the small bridge API described in section 3.
There is no separate main.js file, no folder structure, and no zip — it's
one JSON file with the code inlined as a string.
{
"formatVersion": 1,
"id": "yourname.your-extension",
"name": "Your Extension",
"version": "1.0.0",
"description": "One sentence describing what it does.",
"author": "Your Name",
"main": "main.js",
"icon": "https://example.com/icon.png",
"permissions": {
"network": ["https://api.example.com"],
"workspace": ["read"],
"editor": ["read"]
},
"contributes": {
"commands": ["yourext.doThing"],
"panels": [],
"editor": {}
}
}| Field | Type | Notes |
|---|---|---|
formatVersion |
number | Always 1 for now. |
id |
string | Must be unique. Convention: namespace.extension-name (e.g. community.mcfunction-tools). This is the key used everywhere (install, enable/disable, uninstall). |
name |
string | Display name shown in the Extensions manager. |
version |
string | Free-form (semver recommended). Not currently checked against anything. |
description |
string | Shown under the name in the manager and install-review screen. |
author |
string | Display only. |
main |
string | Cosmetic only right now. The runtime doesn't read a separate file — it executes code directly. Keep it for future-proofing, but don't rely on it doing anything today. |
icon |
string (https URL) | Loaded as a normal <img src> on the host page — any https URL works, it isn't restricted by the extension's own sandbox. |
permissions |
object | See section 4. |
contributes |
object | commands / panels / editor — declared for documentation purposes. Not read or enforced by the UI yet (it isn't shown in the manager, and doesn't need to match what your code actually registers). Fill it in honestly anyway so it's ready for when the manager starts using it. |
Inside the sandboxed iframe, your code gets a studio global with exactly
two working methods:
studio.ui.registerCommand({
id: 'yourext.doThing', // should match something in contributes.commands
label: 'Do The Thing', // shown next to the Run button in the manager
run: function () {
// your logic here
}
});
studio.ui.registerStatusBarItem({
id: 'yourext.status',
text: 'Ready' // plain text only, rendered with textContent (no HTML)
});That's the entire surface area right now. Specifically:
registerCommand— registers a function the user can trigger manually from the extension's Manage → Commands section in the Extensions manager (there's a "Run" button next to each one). There is no command palette, no keybinding, and no way to trigger it from elsewhere in the editor yet — the user has to open your extension's details and click Run.registerStatusBarItem— adds a text label to the status bar strip at the bottom of the editor. Text-only, updates require calling it again with a new item of the sameidis not currently supported — call it once at startup.
Because the sandbox has allow-scripts but not allow-same-origin, your
code cannot:
- touch
documenton the parent page, read the open file's content, or edit the editor - make real
fetch()calls out to the internet (even to a URL you declared underpermissions.network— see section 4) - read
localStorage, cookies, or anything else belonging to mcbcode.com
If your extension needs any of that, it isn't possible yet — build the
smallest thing that's useful within registerCommand +
registerStatusBarItem for now (e.g. a status bar reminder, a command that
opens a link with window.open — note even that runs inside the iframe, so
test that it actually pops a new tab rather than being blocked).
"permissions": {
"network": ["https://api.example.com"],
"workspace": ["read", "write"],
"editor": ["read", "modify"],
"ui": ["registerCommands", "registerPanels"],
"bedrock": ["read", "modify"]
}Important: every category below is shown to the user on the
install-review and permissions screens, so they know what you're asking for
— but only the ui capabilities that map to registerCommand /
registerStatusBarItem (section 3) are actually wired up to do anything.
network, workspace, editor, and bedrock permissions are declarative
only right now: listing them doesn't grant your code real access, and your
code can't actually reach those things yet regardless of what you declare.
Declare them anyway if your extension is designed around them — it costs nothing, keeps the manifest honest about intent, and means you won't have to change it later when those capabilities go live. Just don't ship an extension whose only feature depends on one of these, because it won't work today.
| Category | Example values | Currently enforced? |
|---|---|---|
network |
full URLs, e.g. https://api.curseforge.com |
No — shown to the user, not actually reachable from the sandbox. |
workspace |
read, write |
No — declarative only. |
editor |
read, modify |
No — declarative only. |
ui |
registerCommands, registerPanels, registerToolbarItems, registerStatusBarItems |
Partially — registerCommand/registerStatusBarItem calls work (section 3); the others aren't implemented, so declaring them is just a statement of intent. |
bedrock |
read, modify |
No — declarative only. |
An extension with no permissions object at all is valid and shows
"This extension requests no special permissions."
Save this as wiki-lite.studiomcbc:
{
"manifest": {
"formatVersion": 1,
"id": "yourname.wiki-lite",
"name": "Wiki Lite",
"version": "1.0.0",
"description": "Adds a status bar reminder and a command that opens the Bedrock wiki.",
"author": "yourname",
"main": "main.js",
"icon": "https://mcbcode.com/img/icons/blank-transparent.png",
"permissions": {
"network": ["https://wiki.bedrock.dev"]
},
"contributes": {
"commands": ["wikilite.open"],
"panels": [],
"editor": {}
}
},
"code": "studio.ui.registerCommand({ id: 'wikilite.open', label: 'Open Bedrock Wiki', run: function () { window.open('https://wiki.bedrock.dev', '_blank'); } }); studio.ui.registerStatusBarItem({ id: 'wikilite.status', text: 'Wiki Lite ready' });"
}Note code is a single string — if you're writing multi-line JS, either
keep it minified on one line as above, or JSON.stringify() your source so
newlines get escaped correctly rather than typing \n by hand.
There's no public submission process yet — the Marketplace tab is a fixed, hand-picked list. The only way to get an extension running today is:
- Open Extensions → Manage Extensions (menu bar, or the Extensions icon in the activity bar).
- Install Extension ▾ → Import .studiomcbc.
- Pick your file. You'll land on the install-review screen showing your name, description, and the permissions you declared.
- Click Install Extension.
Extensions installed this way are always marked Unverified (only the
hardcoded Marketplace entries can be Verified) and are stored in the
browser's localStorage, per-browser — not tied to your mcbCode account, so
they won't follow you to another device or browser yet.
-
manifest.idis unique and namespaced (yourname.thing, not justthing) -
codeis valid as a single JS string and only callsstudio.ui.registerCommand/studio.ui.registerStatusBarItem - every
permissionscategory you list is one you'd be honest about even though most aren't enforced yet -
contributes.commandslists the same command ids yourcodeactually registers - you've tested it via Import .studiomcbc yourself before sending it to anyone else
- No command palette or keybindings — commands only run via the manual "Run" button in the extension's details view.
- No real network, file, or editor access from extension code — only the UI bridge in section 3 works.
- No update mechanism — reinstalling an already-installed
idjust returns the existing record rather than overwriting it, so bump the file yourself and have users uninstall + reinstall for now. - Extensions live in browser
localStorage, not your mcbCode account — they don't sync across devices.