The core monorepo for MCX β a domain-specific language (DSL) for building Minecraft Bedrock Edition (MCBE) addons.
Disclaimer: MCX is not affiliated with or endorsed by Mojang/Microsoft. It is an independent, community-driven project.
| Language | Link |
|---|---|
| δΈζ | ./docs/README.zh.md |
MCX is a DSL that compiles .mcx source files into MCBE-compatible JSON components, UI forms, and event systems. It lets you build Minecraft Bedrock addons in a simple, declarative, and type-safe way β without hand-writing hundreds of JSON files.
The pipeline: .mcx file β parser β AST β transform (Babel) β compiled JS β MCBE JSON.
- Component MCX β Generate MCBE component JSON (items, blocks, entities) fast and declaratively
- Form MCX (
<Form>) β Build in-game forms using traditional FormData (ModalFormData / ActionFormData / MessageFormData) - UI MCX (
<Ui>) β Build in-game CustomForm UIs with Observable reactive binding (DDUI) - Explicit form type β Set
type="modal|action|message"on<Ui>or<Form>to override heuristic detection - Nested UI elements β Child elements recursively flattened; grouping containers supported
forloops within/ofβ Iterate over arrays in templates withfor="item in items"orfor="item of items"- Setup system β
<Form setup>/<Ui setup>auto-collect declarations, no manualexportneeded definePropmacro β Compile-time prop declarations with defaults- Lifecycle hooks β
onStartup(once) andonMounted(per show) for setup logic - Event MCX β Subscribe to and handle game events cleanly
- App MCX β Tie components, UI, and events together into a runnable app
- MCX Client β Runtime framework (
createApp,Event,ui,Utils) that runs your app in-game - MCX Compiler β Core compiler with Rollup/Rolldown plugin support, paired with mbler for project scaffolding and builds
- Type-safe β Full TypeScript type definitions for all Minecraft component options, sound events, particle types, and more
- I18n β Built-in internationalization support (en / zh / ja / ko)
- Image assets β PNG, JPG, SVG, and GIF image components for texture generation
This is a pnpm workspace monorepo containing the following packages:
| Package | Version | Description |
|---|---|---|
@mbler/mcx-core |
The DSL compiler β parser, AST, transform pipeline, and Rollup/Rolldown plugins | |
@mbler/mcx |
Runtime framework β createApp, Event, ui, Utils |
|
@mbler/mcx-types |
Shared TypeScript type declarations for MCBE JSON formats | |
@mbler/mcx-component |
Component runtime classes (Item, Block, Entity, Image) used at compile time | |
create-mbler |
CLI scaffolding tool for new mbler projects |
mcx-core/
βββ packages/
β βββ core/ # @mbler/mcx-core β DSL compiler (parser β AST β transform β codegen)
β βββ client/ # @mbler/mcx β runtime framework (createApp, Event, UI)
β βββ types/ # @mbler/mcx-types β shared TypeScript type declarations
β βββ mcx-component/ # @mbler/mcx-component β component runtime classes (Item, Block, Entity, Image)
β βββ create-mbler/ # create-mbler β CLI scaffolding tool for new mbler projects
βββ docs/ # README translations (zh, ja, ko) + TODO.md
βββ scripts/ # verify-commit.js (commit-msg hook)
βββ .github/workflows/ # CI (pnpm install β lint:packages β test)
Below is a complete example showcasing all four MCX file types β Component, Event, UI, and App.
<Component>
<items>
<item id="sword.json">sword</item>
</items>
</Component>
<script lang="ts">
import { ItemComponent } from '@mbler/mcx-component';
export const sword = new ItemComponent({
id: 'demo:custom_sword',
name: 'Custom Sword',
components: {},
});
sword.setDam;
</script><Event @after>
playerJoin = onPlayerJoin
</Event>
<script lang="ts">
import { world } from '@minecraft/server';
import { showForm } from '@mbler/mcx';
import form from '../ui/greeting.mcx';
export function onPlayerJoin(event: PlayerJoinAfterEvent) {
const player = world.getPlayers({
name: event.playerName,
});
player.sendMessage('Welcome to the server!');
showForm(form, player, {
playerName: event.playerName,
});
}
</script>Use <Form> for traditional FormData (ModalFormData / ActionFormData / MessageFormData):
<Form>
<label>{{ playerName }}!</label>
<label>Hello</label>
<button click="onClick">Close</button>
</Form>
<script lang="ts">
export function onClick() {
// close the form
}
</script>Use <Ui> for new CustomForm with Observable reactive binding:
<Ui setup>
<title>Settings</title>
<input :value="name">Player name</input>
<toggle :value="enabled">Enabled</toggle>
<slider :value="volume" min="0" max="100">Volume</slider>
<button :if="advanced" click="onAdvanced">Advanced</button>
<button click="handleSave">Save</button>
</Ui>
<script>
import { ref } from '@mbler/mcx';
const name = defineProp('Player'); // β ObservableString
const enabled = defineProp(false); // β ObservableBoolean
const volume = defineProp(50); // β ObservableNumber
const advanced = ref(true); // ref() works too
function onAdvanced() {
advanced.value = !advanced.value;
}
function handleSave() {
// name.getData() gets current value
}
</script>defineProp accepts string / boolean / number literal defaults (including template
literals and negative numbers) and wraps them in the matching Observable automatically.
Non-literal defaults are passed through as plain values.
Reactive bindings: {{ x }} interpolation unwraps Ref/Observable values,
:value gives two-way binding, :if toggles visibility live, and
:disabled / :tip / :description accept Ref/Observable bindings.
Elements inside for="x in list" loops support :if and the other attributes too.
<script lang="ts">
import event from './events/player_join.mcx';
event.subscribe();
// also can use: event.subscribe("playerJoin")
</script>import app from './app.mcx';
import { createApp } from '@mbler/mcx';
import { world } from '@minecraft/server';
createApp(app).mount(world);More Usage See Bedwars Addon
# Using the create-mbler CLI
pnpm create mbler# Install the compiler and runtime
pnpm add -D @mbler/mcx-core
pnpm add @mbler/mcxThen configure your bundler (Rollup/Rolldown) with the MCX plugin and start writing .mcx files.
For full documentation and tutorials, visit the Docs.
| Layer | Technology |
|---|---|
| Language | TypeScript (strict mode) |
| Package manager | pnpm 11 |
| Build | Rolldown |
| Bundler plugins | Rollup / Rolldown plugin for .mcx files |
| AST | Babel (@babel/parser, @babel/generator, @babel/types) |
| Type system | @volar/language-core for language service |
| Testing | Vitest |
| Linting | ESLint + Prettier |
| CI | GitHub Actions |
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Lint all packages
pnpm lint:packages
# Full check (lint + test + typecheck)
pnpm check
# Format code
pnpm formatContributions are welcome! Please read the Contributing Guide before submitting a pull request.
Before committing, make sure to run:
pnpm checkCommit messages must follow the conventional commits standard (enforced via git hooks).