Custom scripts
Custom scripts let you extend discord-mcbe’s features with JavaScript or TypeScript. discord-mcbe loads the script when the bot starts, allowing you to receive events and control worlds and players.
At startup, discord-mcbe loads the file specified by script.entry in config.json and calls its default export function. The function receives discord-mcbe’s Application instance as its argument.
Minimal script
Section titled “Minimal script”Both JavaScript and TypeScript are supported.
import type { Application } from '@discord-mcbe/server';
export default function main(app: Application) { app.logger.info('Custom script loaded');}/** * @param {import('@discord-mcbe/server').Application} app */export default function main(app) { app.logger.info('Custom script loaded');}Authenticate BDS connections (optional)
Section titled “Authenticate BDS connections (optional)”BDS ServerNet connections are unauthenticated by default. To use Bearer authentication, add a token to .env and configure the authenticator from a custom script.
BRIDGE_TOKEN=your-tokenimport { bearerAuth, type Application } from '@discord-mcbe/server';
export default function main(app: Application) { const token = process.env.BRIDGE_TOKEN; if (!token) throw new Error('BRIDGE_TOKEN is not set');
app.minecraft.script.setAuthenticator(bearerAuth(token));}Set the same token in the BDS variables.json file:
{ "BRIDGE_URL": "ws://localhost:23191", "BRIDGE_TOKEN": "your-token"}For custom authentication, pass a function receiving the request to setAuthenticator. It can return a boolean or Promise<boolean>. A rejected connection never creates a world session.
Subscribe to events
Section titled “Subscribe to events”import type { Application } from '@discord-mcbe/server';
export default function main(app: Application) { app.on('worldConnect', async (event) => { app.logger.info('Connected:', event.world.name); await event.world.sendMessage('§aDiscord bridge connected'); });
app.on('playerJoin', async (event) => { const location = await event.player.getLocation(); app.logger.info(`${event.player.name} joined. Location: [${location.x}, ${location.y}, ${location.z}]`); });
app.on('minecraftMessage', (event) => { app.logger.info('Chat:', event.world.name, event.sender.name, event.message); });}/** * @param {import('@discord-mcbe/server').Application} app */export default function main(app) { app.on('worldConnect', async (event) => { app.logger.info('Connected:', event.world.name); await event.world.sendMessage('§aDiscord bridge connected'); });
app.on('playerJoin', async (event) => { const location = await event.player.getLocation(); app.logger.info(`${event.player.name} joined. Location: [${location.x}, ${location.y}, ${location.z}]`); });
app.on('minecraftMessage', (event) => { app.logger.info('Chat:', event.world.name, event.sender.name, event.message); });}The main events are listed below. See the API reference for details.
| Event | Main values | Emitted |
|---|---|---|
startup |
app |
After the bot, bridge servers, and script have started |
discordReady |
client |
After the bot logs in |
discordMessage |
message |
When a user posts in the relay channel |
discordSend |
channel, message |
Immediately before discord-mcbe sends to Discord |
worldConnect |
world |
When a world finishes initializing |
worldDisconnect |
world |
When a world session ends |
minecraftMessage |
world, sender, message |
On Minecraft chat |
playerJoin / playerLeave |
world, player |
When a player joins or leaves |
Control a world
Section titled “Control a world”import type { Application } from '@discord-mcbe/server';
export default function main(app: Application) { app.on('worldConnect', async ({ world }) => { const result = await world.runCommand('weather clear'); const tps = await world.getTPS();
app.logger.info(world.name, result, 'TPS:', tps); });}/** * @param {import('@discord-mcbe/server').Application} app */export default function main(app) { app.on('worldConnect', async ({ world }) => { const result = await world.runCommand('weather clear'); const tps = await world.getTPS();
app.logger.info(world.name, result, 'TPS:', tps); });}ScriptWorld provides messaging, commands, TPS, script events, player access, and scoreboards. ScriptPlayer provides direct messages, position, dimension and game-mode queries, game-mode changes, kicking, and screen display controls.
See the API reference for the full set of methods and types.
Add dependencies
Section titled “Add dependencies”Custom scripts can use packages published on npm. Add the packages you need to the package.json in the same directory as the launcher. You can choose any package manager, including npm, pnpm, and Bun.
You can import added packages normally from files in scripts/. @discord-mcbe/server and @discord-mcbe/shared are provided by discord-mcbe, so you do not need to install them separately.