Welcome to MCExtensions

A lightweight and modern way to create server-side extensions using nothing but JavaScript.

No Java knowledge? No problem.
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.

✅ Write scripts in .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:

  1. Install the plugin
    Download MCExtensions-{{version}}.jar and place it in your server’s plugins folder.
    The Plugin can be downloaded on the Download Page.
  2. Start your server
    The plugin will generate its configuration files and a scripts/ folder.
  3. Enable the editor
    Open plugins/MCExtensions/config.yml and set:
    editor: true
  4. 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).
  5. 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.
⚠️ Avoid using /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.

📂 Save scripts to 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.

✨ Use JavaScript instead 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
💡 You can run any command like this:
/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.

⚠️ The editor only works when the server is running locally (e.g. on your own machine). Not supported on remote hosts.

💡 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.

✅ Works with commands defined using 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.

Block suggestion preview
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.

Boolean suggestion preview
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.

📌 Every script must start by registering its own extension using MCExt.registerExtension.
⚠️ The extension name must match the pattern [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() and callAfterTime()
  • 🌍 Read and write blocks in the world with setBlock() and getBlock()
⚠️ Calling 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

✅ MCExtensions automatically cleans up registered commands and timers when an extension is unloaded. You do not need to manually unregister anything.

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.

⚠️ If the slot index is out of bounds, an error will be thrown.

Setting Items

inv.setItem(0, new MCStack(new MCResource("diamond"), 1));

Sets the item at the given slot to the specified stack.

⚠️ You must ensure the slot is valid — use 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().

⚠️ Using an invalid slot index (negative or too large) will throw an error.

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.

✅ Time changes are applied instantly to all players in the world.
❗ 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.

⚠️ If the resource passed to 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.

⚠️ If the name does not resolve to a valid resource, an error is thrown.

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.

✅ The metadata is mutable — calling 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<>
MCExt is globally available — no need to import or include it.
✅ 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 player
  • MCPos — A 3D position (with optional world)
  • MCWorld — A world reference
  • MCResource — An item/block type
  • MCStack — A stack of items
✅ Always returns the same shared reference (not cloned)
✅ 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

🧠 Created with 💙 by goldenegg000!

Have questions, feedback, or want to contribute? Join the official MCExtensions Discord server:


👉 Join the Discord

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!

✅ Latest Version: a1.0.0+mc1.20.1-SNAPSHOT ALPHA
📦 Download: MCExtensions-a1.0.0+mc1.20.1-SNAPSHOT.jar
🕒 Released on: 23 April 2025, 21∶20∶35
⚠️ This is an early alpha snapshot. Expect breaking changes.
The JavaScript API is still evolving and may change significantly in future versions.

💬 Found a bug or have feedback? Let us know.