Welcome to MCExtensions
A lightweight and modern way to create server-side extensions using nothing but JavaScript.
MCExtensions lets you skip the Spigot plugin boilerplate and jump right into scripting your server.
With traditional plugins, you'd need to write Java, compile your code, restart the server, and hope
nothing breaks.
MCExtensions skips all of that.
.js
files✅ Use built-in APIs like
MCPlayer
, MCPos
, and more✅ Reload instantly with
/extensions reload
✅ Errors won't crash your server — they're shown in chat with helpful details when possible
Whether you're building utility commands, automations, or gameplay tweaks — this is the easiest way to extend your Minecraft server in real time.
Getting Started
Setting up MCExtensions is quick and simple. You'll be writing server-side JavaScript in no time. Just follow these steps to get everything ready:
-
Install the plugin
DownloadMCExtensions-{{version}}.jar
and place it in your server’splugins
folder.
The Plugin can be downloaded on the Download Page. -
Start your server
The plugin will generate its configuration files and ascripts/
folder. -
Enable the editor
Openplugins/MCExtensions/config.yml
and set:
editor: true
-
Access the web editor
Use the command/editor
in-game. It will post a clickable link in chat.
⚠️ This only works if the server is running locally (not hosted remotely). -
Use the latest GraalVM
For the best performance and JavaScript support, it's highly recommended to install the latest version of GraalVM (Java 23+).
While other Java runtimes may work, they often result in significantly lower performance.
/reload
from Minecraft directly — it may break the plugin.
Use /extensions reload
instead to reload your scripts safely.
🧪 Example Scripts
Once you're set up, try these real examples to get a feel for scripting with MCExtensions.
plugins/MCExtensions/scripts/
🔄 Use
/extensions reload
to refresh them in-game🌐 Or use
/editor
to open the built-in web-based editor in your
browser
⚠️ Only works on local servers (not remote hosts)
👋 Hello Command
const ext = MCExt.registerExtension("hello", {
description: "Says hi!"
});
ext.command({
name: "hello",
usage: "/hello",
description: "Greets the player.",
execute({ player }) {
player.sendMessage("Hello, " + player.getName() + "!");
}
});
🎁 Starter Kit Command
const { MCStack, MCResource } = include();
const ext = MCExt.registerExtension("starterKit", {
description: "Adds Kits."
});
ext.command({
name: "kit",
description: "Gives basic tools.",
usage: "/kit",
execute({ player }) {
const inv = player.getInventory();
inv.addItem(new MCStack(new MCResource("stone_pickaxe"), 1));
inv.addItem(new MCStack(new MCResource("stone_axe"), 1));
player.sendMessage("Tools delivered!");
}
});
🧱 Place a Block
const { MCPos, MCResource } = include();
const ext = MCExt.registerExtension("blockDrop", {
description: "An extension."
});
ext.command({
name: "dropblock",
usage: "/dropblock",
description: "Places a diamond block below you.",
execute({ player }) {
const pos = player.getPosition();
pos.y -= 1;
ext.setBlock(pos, new MCResource("diamond_block"));
player.sendMessage("Boom. Fancy floor.");
}
});
🚀 Knockback Launch
const ext = MCExt.registerExtension("yeet", {
description: "An extension."
});
ext.command({
name: "yeet",
usage: "/yeet",
description: "Launch yourself upward!",
execute({ player }) {
player.push(0, 2, 0);
player.sendMessage("Fly, you fool!");
}
});
🕛 Timer-based Action
const ext = MCExt.registerExtension("repeatMsg", {
description: "An extension."
});
ext.callOnTimer({
interval: 100, // every 5 seconds (20 ticks * 5)
callback() {
ext.sendServerMessage("This message repeats every 5 seconds.");
}
});
Features
MCExtensions provides a clean and intuitive JavaScript API to define custom commands, interact with players, handle inventory, manipulate the world, and much more — all without writing a single line of Java.
🔁 Reload scripts without restarting the server
🧩 Define commands with full argument specs, types, and tab suggestions
🧠 Script logic using in-game entities, positions, inventories, and world control
🔧 Built-in Commands
MCExtensions comes with powerful core commands to help you interact with extensions easily:
/extensions
– View and run all registered extensions/extensions reload
– Reload all active extensions/extensions unload
– Unload all extensions/extensions <extension> <command>
– Run a specific command from an extension/.
– Shorthand for running extension commands (only shows commands, not extensions)/editor
– Show a link to the integrated web-based editor
/extensions myExtension greet
Or just:
/. greet
📝 Integrated Web Editor
Don't have a code editor like VSCode? No problem. MCExtensions includes a built-in browser-based editor with advanced features like:
- 📄 File explorer for editing your
scripts/
folder - 🧠 JavaScript IntelliSense with autocompletion from a bundled definition file
- 🔥 Optional hot-reload toggle when saving files
- 🌐 No installation required — just enable it and go!
To use the editor, enable it in config.yml
by setting editor: true
, then
start/restart the server and run
/editor
in-game to get a link.
💡 Tab Completion Support
One of the best features of MCExtensions is its built-in tab-completion system. As you type command arguments, the plugin will automatically suggest valid options based on the expected input type.
ext.command()
✅ Suggestions are based on argument types like
MCResource
, boolean
,
int
✅ Makes commands more user-friendly and discoverable
1. Block Resource Suggestions
When using a command like:
/extensions myGiveCommand give
,
the second argument (the item name) expects an MCResource
. This triggers intelligent
suggestions for blocks or items.

ext.command({
name: "give",
description: "Gives the player a specified item and amount.",
usage: "/give <item> <amount>",
args: {
item: "MCResource",
amount: { type: "int", default: 1 }
},
execute({ player, args }) {
const stack = new MCStack(args.item, args.amount);
player.getInventory().addItem(stack);
player.sendMessage(`Gave you ${args.amount} of ${args.item.getName().toLowerCase()}.`);
}
});
2. Boolean Value Suggestions
For commands that expect a boolean
(true/false), the tab suggestions will provide both
values for convenience. For example, typing /. fly
shows both options.

ext.command({
name: "fly",
description: "Toggles flight for the player.",
usage: "/fly <true|false>",
args: {
permission: "boolean"
},
execute({ player, args }) {
player.setAllowedFlight(args.permission);
player.sendMessage("Flight mode: " + args.permission);
}
});
API Reference
Welcome to the API Documentation
This is the official reference for the MCExtensions JavaScript API — your gateway to creating powerful and dynamic Minecraft server extensions using nothing but JavaScript.
Every class, method, and function listed here is directly accessible from within your extension scripts. Whether you're interacting with players, modifying the world, creating custom commands, or accessing server data, this API gives you the tools to do it efficiently and cleanly.
On the left, you'll find a categorized navigation panel listing all available classes and utilities. Click any item to jump straight to its definition, examples, and usage notes.
💡 Tip: If you're using the built-in editor, this documentation is fully compatible with
autocomplete suggestions
powered by the mcextensions-api.d.ts
definition file.
MCExtClass
The MCExtClass
is the main entry point to the MCExtensions API. It is
accessible globally via the
MCExt
constant in your scripts.
Its primary role is to register new extensions, which serve as containers for your custom
commands, behaviors, and logic.
Registering an extension returns a MCHandler
, which you'll use to define
commands, interact with players,
and more.
MCExt.registerExtension
.
[A-Za-z0-9_-]+
Only letters, numbers, underscores (
_
) and hyphens (-
) are
allowed.
Example
const ext = MCExt.registerExtension("myExtension", {
description: "My custom extension"
});
In this example, we register a new extension called "myExtension"
with an
optional
description.
The returned ext
(MCHandler) can now be used
to define commands, schedule timers, log
messages, and more.
MCHandler
The MCHandler
object is returned when you register an extension using
MCExt.registerExtension()
. It serves as the main interface to define commands,
access metadata,
and interact with the extension runtime.
This handler allows you to:
- 🧩 Define multiple custom commands via
command()
- 📋 Access and update extension metadata (name, description)
- 🪵 Write formatted log messages to the server console (not the in-game chat)
- 🕛 Schedule repeating or delayed callbacks with
callOnTimer()
andcallAfterTime()
- 🌍 Read and write blocks in the world with
setBlock()
andgetBlock()
command()
with the same command name more than once will throw an
error.
Command names must be unique within each extension.
Basic Command Example
ext.command({
name: "hello",
description: "Sends a friendly greeting",
usage: "/hello",
execute({ player }) {
player.sendMessage("Hello!");
}
});
Logging to the Server Console
ext.log("Hello from extension!");
ext.warn("Something may be wrong...");
ext.err("Something went wrong!", error);
These logging methods support multiple arguments and are printed to the server console, not the in-game chat. They are useful for debugging, tracking extension behavior, or warning about misusage.
Accessing and Modifying Extension Metadata
const meta = ext.getMetaData();
ext.log("Extension name:", meta.getName());
meta.setDescription("Updated description");
ext.setMetaData(meta);
Cleanup
MCPlayer
MCPlayer
represents a player currently online on the server. This class
provides a variety of methods to
interact with the player — such as sending messages, modifying health, changing flight
permissions, accessing their inventory,
and teleporting them around the world.
Sending Messages
player.sendMessage("Welcome!");
player.sendMessage("You have", player.getXpLevel(), "XP levels.");
You can pass multiple arguments to sendMessage()
, and each one will be sent as
a separate message line in the chat.
Teleporting the Player
const pos = player.getPosition();
pos.y += 10;
player.setPosition(pos);
setPosition()
moves the player to the specified location. It does not perform
safety checks —
it is your responsibility to ensure the destination is valid (e.g. not inside blocks or
void).
Velocity and Push
player.push(0, 1, 0); // Applies an upward knockback-style effect
The push()
method adds to the player's velocity, making it behave like
knockback or launching.
Health Control
player.setHealth(10);
ext.log("Current health:", player.getHealth());
Health values are clamped automatically between 0
and 20
, the
default maximum for players.
Flight Control
player.setAllowedFlight(true);
ext.log("Flight enabled:", player.allowedFlight());
This enables or disables whether the player can fly — not whether they are currently flying.
Inventory Access
const inv = player.getInventory();
inv.clear();
The player's inventory can be accessed at any time via getInventory()
. See
MCInventory
for details.
MCInventory
MCInventory
represents any inventory such as from a Player. It provides methods
to
inspect, modify, and manage the contents of the inventory — including adding items, setting
specific slots, and clearing everything.
Accessing the Inventory
const inv = player.getInventory();
You can safely access the inventory of any player using getInventory()
. This
always returns a valid MCInventory
instance.
Clearing All Items
inv.clear();
Completely removes all items from the inventory.
Getting Items
const item = inv.getItem(0);
Returns an MCStack
representing the item at the given slot.
Setting Items
inv.setItem(0, new MCStack(new MCResource("diamond"), 1));
Sets the item at the given slot to the specified stack.
size()
to get the inventory size.
Adding Items
const leftover = inv.addItem(new MCStack(new MCResource("stone"), 100));
Attempts to add an item stack to the inventory. It will fill existing partial stacks first, then empty slots. If the inventory is full, it returns a map of leftover items that couldn’t be added:
// Example output:
{
36: MCStack { ... },
37: MCStack { ... }
}
Checking Inventory Size
ext.log("Inventory has", inv.size(), "slots");
The number of slots depends on the inventory type. Always use size()
to
determine bounds before using getItem()
or setItem()
.
MCPos
MCPos
represents a location in the world. It holds three coordinates:
x
, y
, and z
,
along with an optional world
property.
Creating and Modifying Positions
const pos = new MCPos(10, 68, 143);
player.setPosition(pos);
const pos = player.getPosition();
pos.y += 5;
player.setPosition(pos);
Position values (x
, y
, z
) are
doubles and can be modified freely in JavaScript.
You can directly update the properties to move or offset positions.
Working with Worlds
pos.world = MCWorld.NETHER;
You can assign a specific world to a position using pos.world
. If no world is
defined, MCExtensions will attempt to use
a fallback — such as the world the player is currently in, or the OVERWORLD
when relevant.
MCPos
is used in many contexts — such as teleporting players, placing blocks,
or checking coordinates.
It’s designed to be flexible and works with MCPlayer
, MCWorld
, and
other APIs.
Format String
ext.log(pos.getFormatString());
Outputs a string representing the full coordinates and world, useful for logging or debugging.
Example Use for Block Placement
const blockPos = player.getPosition();
blockPos.y -= 1;
ext.setBlock(blockPos, new MCResource("stone"));
This example places a block one unit below the player using a valid MCPos
.
MCWorld
MCWorld
represents a specific world on the Minecraft server. It's commonly used
when dealing with positions (MCPos
),
or for interacting with world-level data like time.
Predefined Worlds
pos.world = MCWorld.OVERWORLD;
pos.world = MCWorld.NETHER;
pos.world = MCWorld.END;
You can reference the default Minecraft worlds using the constants
MCWorld.OVERWORLD
, MCWorld.NETHER
, and MCWorld.END
.
Getting and Setting Time
const world = pos.world;
ext.log("Current world time:", world.getTime());
world.setTime(6000); // Noon
World time is represented as ticks, ranging from 0
(sunrise) to
24000
(full day).
Calling setTime()
updates the time immediately for all players in that world.
Retrieving the World Name
ext.log("World name:", world.getName());
This returns the internal name of the world, such as "world"
or
"world_nether"
. It corresponds to the name used in your server’s world folders.
❗ Custom dimensions are not yet supported in the API.
MCStack
MCStack
represents a stack of items — combining both the
MCResource
(item type) and the amount.
It is commonly used when adding or modifying a player's inventory.
Creating an Item Stack
const stack = new MCStack(new MCResource("stone"), 64);
You must provide both the MCResource
and a positive integer amount.
Omitting the amount or passing a value less than 0 will throw an error.
Working with Stacks
stack.setAmount(10);
stack.setResource(new MCResource("diamond_sword"));
ext.log("Amount:", stack.getAmount());
ext.log("Item name:", stack.getResource().getName());
You can change both the item type and the quantity at any time.
getAmount()
returns a number, and getResource()
returns a copy of
the associated MCResource
.
MCStack
is not a valid item (e.g. a block-only
material), it will throw an error.
Checking for Item Validity
const res = new MCResource("stone");
if (res.isItem()) {
const stack = new MCStack(res, 32);
}
Use the isItem()
method to check if a resource is valid for Stack-related
actions.
MCStack
supports all item types (blocks, tools, food, redstone, etc.)❗ There is no hardcoded upper limit on amount, but values above the typical Minecraft max (64) may behave unexpectedly.
MCResource
MCResource
represents a block or item type in Minecraft, such as
stone
or minecraft:diamond_sword
.
It is used whenever you want to refer to a resource in inventory operations or world
interactions.
Creating a Resource
const res = new MCResource("stone");
const sword = new MCResource("minecraft:diamond_sword");
The constructor accepts either a simple name ("stone"
) or a full namespaced ID
like "minecraft:stone"
.
Internally, the string is uppercased and passed to Bukkit’s
Material.matchMaterial()
method.
Getting the Resource Name
ext.log("ID:", res.getName().toLowerCase()); // stone
getName()
returns the internal enum name (e.g. "WHITE_WOOL"
).
Use .toLowerCase()
in JS to convert it to lowercase formatting if needed.
Checking Type
if (res.isItem()) {
ext.log("This is a valid item");
}
if (res.isBlock()) {
ext.log("This is a valid block");
}
Use isItem()
and isBlock()
to verify if the resource is usable in
inventories or block placement respectively.
MCResource
is required for actions like placing blocks, giving items, and
creating stacks.✅ Works with both items and blocks.
❗ Invalid resource names will immediately throw errors.
ExtensionMetaData
ExtensionMetaData
holds the name and description of your extension.
You can use it to retrieve or change the visible identity of your script.
Accessing Metadata
const meta = ext.getMetaData();
ext.log("Extension name:", meta.getName());
ext.log("Description:", meta.getDescription());
Use getMetaData()
on your extension handler to retrieve this object at any
time.
Changing Metadata
meta.setName("coolerName");
meta.setDescription("This plugin just got renamed.");
You can modify the name and description dynamically while the server is running.
The updated values are reflected immediately in output like /extensions
and tab
completion.
setName()
or setDescription()
updates it live.✅ Changing the name updates how the plugin is referenced in commands (e.g.
/extensions newName
).❗ These values are not persisted across restarts — they reset to what's in the original script.
MCExt
MCExt
is the global object available in every script.
It's the entry point for registering new extensions and interacting with the MCExtensions
system.
Registering an Extension
const ext = MCExt.registerExtension("myPlugin", {
description: "An example plugin created using MCExtensions."
});
The registerExtension
method creates a new extension instance and returns an
MCHandler
.
The name must only contain letters, numbers, underscores, or dashes
([A-Za-z0-9_-]+
).
toString()
console.log(MCExt.toString()); // MCExt<>
✅ Used to register and identify extensions.
❗ Only two methods are available:
registerExtension()
and
toString()
.
include()
include()
is a global function used to access native Java-backed classes such
as MCPlayer
, MCStack
, and others.
It must be called in every script that wants to use these types.
const { MCPlayer, MCStack, MCPos } = include();
The function returns the same reference every time and exposes:
MCPlayer
— Represents a playerMCPos
— A 3D position (with optional world)MCWorld
— A world referenceMCResource
— An item/block typeMCStack
— A stack of items
✅ Classes are constructors, so use
new
to instantiate (e.g.
new MCStack(...)
)❗ Required in each script file that uses native types — they are not globally scoped
Contact & Credits
Have questions, feedback, or want to contribute? Join the official MCExtensions Discord server:
Download MCExtensions
Grab the latest version of the MCExtensions plugin here. Just drop the .jar
file into
your
server's plugins
folder and you're good to go!
📦 Download: MCExtensions-a1.0.0+mc1.20.1-SNAPSHOT.jar
🕒 Released on: 23 April 2025, 21∶20∶35
The JavaScript API is still evolving and may change significantly in future versions.
💬 Found a bug or have feedback? Let us know.