Introduction
mc is a command line tool to manage and run Minecraft instances.
An instance is described by a single manifest file, mc.kdl. From that one
file, mc run takes care of everything needed to bring the instance up:
- installs a Java runtime
- installs Minecraft for the configured version
- installs a mod loader, when one is configured
- downloads mods and resolves their dependencies into a lockfile
- writes the configuration files Minecraft expects
- launches the instance and supervises it until it stops
- takes scheduled world backups to local storage or S3
If you have used a package manager, the workflow will feel familiar: a declarative manifest, a generated lockfile, and a small set of commands that operate on them.
mc init myserver --eula
cd myserver
mc run
Sections
Install mc and start your first instance.
Task-oriented guides: managing mods, configuring backups, and deploying an instance as a systemd service.
The mc.kdl manifest format, the environment variables mc reads, and the
on-disk layout of an instance.
Detailed documentation for every mc command.
Getting Started
To get started with mc:
- Installation — install the
mcbinary on your system. - First Steps with mc — create an instance and run it.
Installation
mise
mise installs the latest release binary and puts it
on your PATH:
mise use -g github:afrigon/mc
Pre-built binaries
Every release publishes pre-built binaries on the GitHub releases page for:
- Linux (
x86_64,aarch64) - macOS (
x86_64,aarch64) - Windows (
x86_64)
Download the archive for your platform, extract it, and place the mc binary
somewhere on your PATH:
tar -xzf mc-linux-x86_64.tar.gz
install -m 755 mc /usr/local/bin/mc
mc --version
Building from source
mc is written in Rust and builds with a recent stable toolchain:
git clone https://github.com/afrigon/mc
cd mc
cargo build --release
The binary is produced at target/release/mc.
First Steps with mc
This walkthrough creates a new instance and runs it.
Create an instance
Each instance lives in its own directory, with a mc.kdl manifest at its
root. mc init creates both:
mc init myserver
cd myserver
The generated manifest looks like this:
name "myserver"
description "A Minecraft Server"
minecraft {
version "..."
loader "fabric"
}
server {
gamemode "survival"
difficulty "normal"
hardcore #false
// Setting this to true indicates YOU have read and agree to the Minecraft EULA (https://aka.ms/MinecraftEULA).
// This agreement is between you and Mojang/Microsoft.
eula #false
}
backups {
enabled #true
frequency "0 0 * * * *"
}
mods {
modrinth {
lithium "..."
}
}
By default mc init uses the optimized preset, which adds a mod loader and
a small set of performance mods. Pass --preset vanilla for an unmodded
instance. The manifest is yours to edit; every key is documented in
The Manifest Format.
Agree to the EULA
The instance will not start until you have agreed to the Minecraft EULA. Once you have read it, set:
server {
eula #true
}
You can also pass --eula to mc init to do this at creation time.
Run it
mc run
On first run, mc downloads a Java runtime, the Minecraft binary, the mod loader, and any configured mods, then starts the instance. Subsequent runs reuse what is already installed and start immediately.
The console is attached to your terminal. Stop the instance with Ctrl-C:
mc asks it to save the world and waits for it to exit cleanly.
Note that the allow list is enabled by default, so players must be on it
before they can join. Add them with mc allow add.
To open the instance to everyone instead, set allow-list #false in the
server section.
Next steps
- add or update mods with
mc addandmc update— see Managing Mods - decide who may join and who holds commands — see Players
- configure world Backups
- let players outside your network join — see Tunnels
- deploy the instance as a service — see Running under systemd
Guides
Task-oriented guides for operating an instance:
- Managing Mods — add, remove, and update mods.
- Players — the allow list, bans, and operators.
- Backups — scheduled and manual world backups, and restoring from them.
- Running under systemd — deploy an instance as a supervised service.
- Tunnels — let players join from outside the local network without forwarding ports.
Managing Mods
Mods are declared in the mods block of mc.kdl, grouped by source, and
installed when the instance starts. Under modrinth, each node names a mod
by its identifier on the mod registry and pins the version to install:
minecraft {
version "..."
loader "fabric"
}
mods {
modrinth {
lithium "..."
}
}
A mod loader must be configured under minecraft for mods to be installed;
without one, the mods block is ignored. See
The Manifest Format for the other groups,
including mods fetched from a direct URL.
Adding and removing mods
mc add and mc remove edit
the modrinth group for you. mc add looks the mod up on the registry and pins
the latest version compatible with the configured Minecraft version and
loader:
mc add sodium lithium
mc remove sodium
Updating mods
mc update re-pins mods to the latest compatible
version — every mod in the manifest, or only the ones you name:
mc update
mc update lithium
Mods fetched from a direct URL have no version to compare and are skipped.
How mods are installed
Changes to mods take effect the next time the instance starts. On
startup, mc resolves each entry — including its required dependencies — and
records the result in the mc.lock lockfile. It then downloads any mod that
is missing and deletes any mod that is no longer in the lockfile.
Two consequences of this are worth knowing:
- You do not need to declare a mod’s dependencies; they are resolved and installed automatically.
- The instance’s
modsdirectory is fully managed by mc. A jar placed there by hand is removed on the next start. To install a mod that is not on the registry, declare it in the manifest under thehttpgroup instead.
Players
Who may join an instance, who is kept out, and who holds server commands
are all declared in the players section of mc.kdl and written to the
server when the instance starts:
players {
allow {
Notch
jeb_
}
ban {
Griefer reason="stole the beacon" created="2026-09-06T14:00:00Z"
}
op {
Notch level=4
}
}
See The Manifest Format for every key. The
allow list is enabled by default; to open the instance to everyone, set
allow-list #false in the server section. Operators may join regardless
of the allow list.
Editing the lists
mc allow, mc ban, and
mc op edit the section for you. Each has add,
remove, and list subcommands:
mc allow add Notch jeb_
mc ban add Griefer --reason "stole the beacon" --for 7d
mc op add Notch
mc op list
Names are looked up when added, so a typo fails at the command rather than at the next start, and the account’s own casing is recorded. Names are matched regardless of case afterwards.
How the lists reach the server
The server keeps its lists in JSON files inside instance/. mc regenerates
them from the manifest on every start, so the manifest is the single
source of truth and those files are never edited by hand. Each player’s
identity is resolved once and remembered in mc.lock, so a start never
waits on a lookup.
When the instance is running and its remote console is reachable, a command also applies the change to it right away, so a newly banned player is disconnected and a newly allowed one can join without a restart. The remote console is reachable when an RCON password is configured — see Environment Variables. Two kinds of change cannot be applied live and wait for the next restart: an operator level or player limit bypass, and a ban expiry. The command says so with a warning.
Changes made from inside the game, such as /ban or /op typed by an
operator, live only in the server’s files and are replaced by the manifest
at the next start. Put them in the manifest with the matching mc command
to keep them.
Offline mode
An instance with online-mode #false in the server section does not
verify accounts, and the server identifies players by name alone. mc
derives the identity the server expects from the name, so no lookup happens
and any name is accepted.
Backups
mc can archive the instance’s world on a schedule while it runs, and restore any archive later. Backups are coordinated with the running instance so the world is flushed to disk before it is captured — archives are always consistent, even under load.
Scheduled backups
backups {
enabled #true
frequency "0 0 * * * *"
}
With enabled #true, backups fire on the frequency schedule while the
instance runs. Without it, or with a manifest that has no backups section,
nothing is scheduled. frequency is a cron expression with six fields — seconds,
minutes, hours, day of month, month, day of week. The example above backs up
at the start of every hour.
Coordination with a running instance happens over RCON, Minecraft’s remote
console protocol. RCON is enabled whenever an RCON password is configured;
when backups are enabled and no password is set, mc generates one at startup
so backups work out of the box. See
MC_RCON_PASSWORD to set the
password yourself.
Manual backups
A backup can be taken at any time with
mc backup, even when scheduled backups are
disabled — enabled only controls the schedule. It works against a stopped
instance, and against a running one as long as the instance was started with
an RCON password configured (always the case when backups are enabled). When
the instance is running but cannot be reached, mc refuses to back up rather
than capture a world that is still being written to.
Interruptions
Backups are safe to interrupt. Ctrl-C cancels a backup in progress: the
partial archive is discarded and the instance’s auto-save is re-enabled
before the error is reported — the same recovery runs when a backup fails
on its own. Stopping an instance while a scheduled backup is running
cancels the backup the same way.
A backup killed with no chance to clean up (power loss, SIGKILL) cannot re-enable auto-save. As a last line of defense, mc turns auto-save on whenever an instance starts, as soon as it accepts remote console connections.
Storage
Archives go to the storage target named in the backups section: local
or s3, never both. When neither is written, archives go to the backups
directory of the instance.
Local stores archives in a directory and keeps only the keep most
recent automatic ones:
backups {
keep 20
local "/mnt/data/mc"
}
Archives appear in the directory atomically: an interrupted backup never leaves a partial archive under a backup name or damages the backup it was about to replace.
S3 uploads archives to a bucket:
backups {
s3 "my-minecraft-backups" region="us-east-1"
}
Credentials come from the standard AWS credential chain (environment,
~/.aws, or an IAM role), and so does the region when region is omitted.
The MC_BACKUPS_S3_BUCKET environment variable overrides the bucket. mc does
not prune S3 backups; use a bucket lifecycle rule to expire old archives.
Give each instance its own bucket or directory. mc treats a file in the
storage target as one of this instance’s backups when its name starts with
the instance name and ends with .tar.gz (for example myserver_*.tar.gz);
anything else is ignored — never listed and never deleted.
Keeping a backup forever
Retention only applies to automatic backups — the timestamped archives
created by the schedule or a plain mc backup. A backup taken with
mc backup --name is stored as
{instance}_{name}.tar.gz, shows up in mc restore --list, and is never
pruned, no matter the keep limit.
Renaming an archive by hand works too: any file in the storage target named
like myserver_important.tar.gz — the instance name, an underscore, and a
label that is not a timestamp — is treated as a named backup: listed,
restorable, and exempt from pruning.
On S3, mc never deletes anything, and a bucket lifecycle rule cannot tell a named backup from an automatic one; scope the rule (for example by key prefix) if named backups must outlive it.
Notifications
mc reports backup results — along with other instance events — to a webhook
when one is configured through the environment (MC_DISCORD_WEBHOOK for
Discord). The notifications section of the manifest selects which
events are sent; see
The Manifest Format. A failed
notification never fails the backup itself.
Restoring
List the available backups, then restore one:
mc restore --list
myserver_2026-07-15_15-00-00.tar.gz (latest)
myserver_2026-07-14_15-00-00.tar.gz
mc restore --backup myserver_2026-07-14_15-00-00.tar.gz
Without --backup, the most recent backup is restored. The instance must be
stopped to restore. The world being replaced is set aside rather than
deleted, and is put back if the restore fails. See
mc restore.
Running under systemd
mc run is designed to live under a process supervisor. It does not restart
the instance when it crashes; it reports the failure through its exit code
and lets the supervisor decide. On Linux, systemd is the natural fit.
Unit file
Assuming an instance at /srv/minecraft/myserver, create
/etc/systemd/system/myserver.service:
[Unit]
Description=myserver Minecraft instance
After=network-online.target
Wants=network-online.target
[Service]
User=minecraft
WorkingDirectory=/srv/minecraft/myserver
ExecStart=/usr/local/bin/mc run --server-logs
EnvironmentFile=/etc/minecraft/myserver.env
Restart=on-failure
[Install]
WantedBy=multi-user.target
Then enable and start it:
systemctl enable --now myserver
WorkingDirectory must be the instance root — the directory containing
mc.kdl — since mc operates relative to it.
Secrets
Environment variables such as MC_RCON_PASSWORD or a notification webhook
are best kept out of the unit file, in an EnvironmentFile readable only by
root, such as /etc/minecraft/myserver.env:
MC_RCON_PASSWORD=...
MC_DISCORD_WEBHOOK=...
See Environment Variables for everything mc reads from the environment.
Stopping and restarting
systemctl stop sends the service SIGTERM. mc catches it, asks the instance
to save the world and shut down, and waits for it to exit before returning —
within systemd’s default stop timeout, so the unit is not killed mid-save.
The same applies to systemctl restart and to stops issued during a system
shutdown.
Restart=on-failure brings the instance back up if it crashes, while a
clean stop (including one requested from inside the game with /stop) stays
stopped.
Logs
With --server-logs, the instance’s console output goes to standard output,
which systemd captures in the journal (add --tunnel-logs to capture the
tunnel agent as well):
journalctl -u myserver -f
mc’s own log verbosity is controlled by the global --verbose flag; the
instance’s console log level follows it.
Tunnels
An instance normally accepts players only from its own network; letting friends in from elsewhere means forwarding a port on the router and sharing a public address. A tunnel removes both steps: a small agent runs beside the instance, keeps an outbound connection to a relay, and the relay hands out a public hostname that reaches the instance through that connection. Nothing on the network needs configuring, and the hostname is what you share.
mc supports playit.gg as the tunnel provider. It is free for a friend group and needs an account, which is created the first time an agent is claimed.
Enabling a tunnel
tunnel {
provider "playit"
}
Adding the section is enough — a bare tunnel node also works; see
tunnel for its keys.
First start
Start the instance from a terminal:
mc run
Claiming tunnel agent, approve it at https://playit.gg/claim/... with your playit.gg account
Claimed tunnel agent secret saved to .tunnel/playit.toml
Creating a Minecraft tunnel for port 25565
Tunnel players can join at quiet-fox.joinmc.link
Opening the link in a browser, signed in to the provider, approves the agent
for that account. mc then stores the agent secret in .tunnel/playit.toml,
readable only by the owning user, creates a Minecraft tunnel for the
instance’s server port when the agent has none, and prints the public
address. Players add that address to their server list as they would any
other; no port is needed.
Later starts skip the claim and reuse the tunnel. The address is stable for as long as the tunnel exists with the provider. When notifications are enabled, the “started” message includes it.
Deleting .tunnel/playit.toml, or running
mc tunnel claim --force, links the instance to a
new agent on the next start.
While the instance runs
The agent runs for as long as the instance does and is restarted by mc if it
stops on its own. Its output is written to .tunnel/playitd.log, or shown in
the terminal when the instance is started with mc run --tunnel-logs.
Stopping the instance stops the agent.
Traffic between players and the instance flows through the provider’s relay, so the address only works while the instance is running.
Under a service manager
The claim needs a browser, and a service has no terminal to print the link
to. When no secret file exists and the instance is not started from a
terminal, mc run fails with instructions instead of waiting. Claim the
agent once beforehand, either by running mc run from a terminal or with
mc tunnel claim, then deploy as described in
Running under systemd. The secret file travels with the
instance directory.
Managing the tunnel
The tunnel itself, its address, and the agent are visible in the provider’s dashboard, where a custom hostname or region can be assigned. When mc cannot create the tunnel, for example because the account has reached the provider’s limits, it prints a warning with a link to the dashboard and keeps running; a tunnel created there for the instance’s server port is picked up on the next start.
Reference
- The Manifest Format — every key of
mc.kdl. - Environment Variables — everything mc reads from the environment.
- Instance Layout — the files and directories that make up an instance.
The Manifest Format
The mc.kdl manifest at the root of an instance describes everything about
it. It is written in KDL. Every section except the two
top-level keys is optional; omitted keys take the defaults listed below.
Unknown keys, repeated keys, and stray values are errors.
name "myserver"
description "A Minecraft Server"
java {
version "graal@25"
min-memory 4096
max-memory 4096
jvm-arguments "-Djava.net.preferIPv6Addresses=true" "-XX:+AlwaysPreTouch" "-Djdk.graal.TuneInlinerExploration=1"
}
minecraft {
version "latest"
loader "fabric"
}
server {
gamemode "survival"
difficulty "normal"
level-type "minecraft:normal"
hardcore #false
allow-list #true
online-mode #true
hide-online-players #true
port 25565
rcon-port 25575
capacity 20
view-distance 16
simulation-distance 16
eula #true
properties {
spawn-protection 0
}
}
mods {
modrinth {
lithium "..."
}
}
backups {
enabled #true
frequency "0 0 * * * *"
keep 20
local "backups"
}
notifications {
on-lifecycle-event #true
on-panic #true
on-sigkill #true
on-backup #true
on-backup-failure #true
}
name (required)
The instance name. It names the world directory inside the instance and is
used as the world’s level-name. Must be usable as a directory name.
description (required)
A short description, used as the message of the day (motd) shown in the
multiplayer list.
java
The Java runtime used to launch the instance.
version— the runtime to install and use, as avendor@versiondescriptor. Defaults to"graal@25". Runmc java listto see the available runtimes; the one marked(recommended)is the default.min-memory— initial heap size in megabytes. Defaults to4096.max-memory— maximum heap size in megabytes. Defaults to4096.jvm-arguments— extra arguments passed to the JVM. Defaults to a small set of tuned flags; setting this key replaces the defaults entirely.
java {
version "graal@25"
min-memory 8192
max-memory 8192
jvm-arguments "-XX:+AlwaysPreTouch"
}
minecraft
The Minecraft version and mod loader.
version— the Minecraft version to run. Defaults to"latest", the latest release."latest-snapshot"selects the latest snapshot, and any exact version id (seemc minecraft list) pins that version. Aliases are resolved every start, so an instance on"latest"upgrades itself when a new release comes out — pin an exact version if that is not what you want.loader— the mod loader, as anameorname@versiondescriptor (for example"fabric", which resolves to the latest loader version for the configured Minecraft version). When omitted, the instance runs without a loader and themodsblock is ignored. Runmc minecraft list-loadersto see loader versions.
tunnel
Exposes the instance to players outside the local network through a tunnel
provider; see the Tunnels guide. The section is
opt-in: when it is absent, no tunnel agent is installed or started. A bare
tunnel node enables it with the defaults.
provider— the tunnel provider, as anameorname@versiondescriptor.playitis the accepted provider. Defaults to"playit", which resolves to the latest agent version on every start; pin an exact version, such as"playit@1.0.10", to hold it. Runmc tunnel listto see the available versions.
tunnel {
provider "playit"
}
server
Settings mc manages for the server. Each maps to a server.properties key,
listed in parentheses; because these are managed here, they cannot be set
through properties.
gamemode—"survival","creative","adventure", or"spectator". Defaults to"survival". (gamemode)difficulty—"peaceful","easy","normal", or"hard". Defaults to"normal". (difficulty)level-type—"minecraft:normal","minecraft:flat","minecraft:large_biomes","minecraft:amplified", or"minecraft:single_biome_surface". Defaults to"minecraft:normal". (level-type)hardcore— defaults to#false. (hardcore)allow-list— whether players must be on the allow list before they can join. Defaults to#true. (white-list) Enabling it also setsenforce-whitelist, so a player removed from the list is kicked at once; disabling it clears both.enforce-whitelistis not managed, so an entry for it inpropertiesoverrides that half on its own.online-mode— whether the server verifies accounts with Mojang. Defaults to#true. (online-mode) See Offline mode for how it changes the way players are identified.hide-online-players— whether the server list ping leaves out the names of the players online. The player count stays visible. Defaults to#true. (hide-online-players)seed— the world seed, as an integer or a string. Random when omitted. (level-seed)eula— indicates that YOU have read and agree to the Minecraft EULA. The instance refuses to start until this is#true. Defaults to#false.ip— the address to bind. When omitted, the server binds all addresses, IPv6 included. (server-ip)port— the game port. Defaults to25565. (server-port)rcon-port— the remote console port. Defaults to25575. (rcon.port)capacity— the maximum number of players. Defaults to20. (max-players)view-distance— in chunks. Defaults to16. (view-distance)simulation-distance— in chunks. Defaults to16. (simulation-distance)
properties
A block inside server holding overrides for any other
server.properties key. mc
generates the file on every start — hand edits do not survive — so this
block is the way to reach settings that have no server field:
server {
properties {
spawn-protection 16
enforce-whitelist #false
"query.port" 25565
}
}
Values may be strings, integers, floats, or booleans. Keys containing a dot
must be quoted, as above; a nested block spells the same key, so
rcon { broadcast "yes" } sets rcon.broadcast.
Any key is accepted, since mods read their own settings from the same
file, but mc run prints a warning for each key in
this block that is not a known server property, so a typo does not go
unnoticed.
Keys managed by mc are rejected: an entry for a key that a server field
or the top-level name and description already drive is an error naming
the field to use instead. Every managed entry is reported in the same
error, so one pass fixes them all. enable-rcon is rejected too — RCON is enabled
exactly when an RCON password is configured (see
Environment Variables).
Every key not written here takes the vanilla default as of Minecraft 26.3,
listed on the server.properties
wiki page, with three exceptions:
enforce-whitelist— followsallow-list, so#trueby default.server-ip—"::", all addresses, IPv6 included; driven byip.spawn-protection—0.
mods
The mods to install, grouped by where they come from. Inside a group, each node is named after the mod and carries where to fetch it:
mods {
// mods from the registry, pinned to a version identifier
modrinth {
lithium "..."
carpet "..."
}
// jars fetched from a URL, for mods not on the registry
http {
my-mod "https://example.com/my-mod.jar"
}
}
modrinth maps a mod’s identifier (slug) on the registry to the version
identifier to install. http maps a name of your choosing to the URL of a
jar. A name may appear in only one group; it becomes the jar’s filename.
mc add, mc remove, and
mc update edit the modrinth group for you and
pin compatible versions. Required dependencies are resolved automatically
when the instance starts and recorded in the mc.lock lockfile — see
Managing Mods.
backups
Scheduled world backups, taken while the instance runs.
enabled— whether backups run on thefrequencyschedule while the instance runs. Defaults to#false, so a manifest without this field, or without abackupssection at all, never schedules a backup. Manualmc backupworks regardless.frequency— a cron expression with six fields: seconds, minutes, hours, day of month, month, day of week. Defaults to"0 0 * * * *"(hourly).keep— the number of most-recent automatic archives to keep in local storage; older ones are pruned. Defaults to20. S3 storage is never pruned.local— the directory archives are stored in. This is the default storage, underbackups, when neitherlocalnors3is written.s3— the bucket archives are uploaded to, with an optionalregionproperty. Credentials come from the standard AWS credential chain, andMC_BACKUPS_S3_BUCKEToverrides the bucket. Withoutregion, the region also comes from the credential chain.
Write at most one of local and s3.
backups {
enabled #true
frequency "0 0 * * * *"
keep 20
local "/mnt/data/mc"
}
backups {
enabled #true
s3 "my-minecraft-backups" region="us-east-1"
}
See the Backups guide for the full picture.
players
Who may join, who is kept out, and who holds server commands. Each group lists players as nodes named after them; a name that starts with a digit must be quoted. Options ride on the node as properties.
players {
allow {
Notch
"123abc"
}
ban {
Griefer reason="stole the beacon" created="2026-09-06T14:00:00Z" expires="2026-10-01T00:00:00Z"
}
ban-ip {
"203.0.113.7" reason="bot traffic"
}
op {
Notch level=4 bypasses-player-limit=#true
jeb_
}
}
allow— players permitted to join whileallow-listinserveris#true, which it is by default. Entries take no properties.ban— players refused by the server.reasonis shown to the player and defaults to the server’s own wording;createdrecords when the ban was issued;expireslifts the ban at that time. Both dates are RFC 3339 timestamps. A player cannot be in bothallowandban.ban-ip— addresses refused by the server, with the same properties asban. Node names are IP addresses and must be quoted.op— operators.levelis the permission level from1to4and defaults to the server’sop-permission-levelproperty;bypasses-player-limitlets the operator join when the server is full and defaults to#false. Operators may join regardless of the allow list.
mc allow, mc ban, and
mc op edit these groups for you and look names up as
they go. The lists are written to the instance on every start — see
Players.
notifications
Webhook notifications about the instance. A provider is activated by
setting its webhook environment variable (MC_DISCORD_WEBHOOK for
Discord) — the URL is a secret and is never read from the manifest, and
without one no notifications are sent. This block selects which events are
reported; every key defaults to #true:
on-lifecycle-event— the instance started or stopped. When a tunnel is configured, the started message includes the address to join at.on-panic— the instance crashed.on-sigkill— the instance was forced down without a clean save, because it did not stop within the grace period or a second stop signal arrived.on-backup— a backup completed.on-backup-failure— a backup failed.
notifications {
on-lifecycle-event #false
on-backup #false
}
Environment Variables
The environment acts as an override layer on top of mc.kdl. Secrets are
deliberately kept out of the manifest so it can be committed and shared
safely: mc reads them from the environment, or from files it generates
readable only by the owning user (see Instance
Layout).
MC_RCON_PASSWORD
The password for RCON, the remote console protocol used to coordinate
backups with a running instance. The environment is the only place it is
read from: a "rcon.password" entry in the properties block of the
server section is rejected, so the secret never lands in the manifest.
RCON is enabled exactly when a password is configured. When backups are enabled and no password is set anywhere, mc generates one at each start so backups work out of the box; set this variable when other tooling needs to reach the remote console with a known password.
MC_BACKUPS_S3_BUCKET
The S3 bucket that receives backup archives when the backups section
names an s3 target. It takes precedence over the bucket written in the
manifest.
S3 credentials are not read through mc-specific variables; they come from
the standard AWS credential chain — AWS_ACCESS_KEY_ID /
AWS_SECRET_ACCESS_KEY, the ~/.aws configuration files, or an attached
IAM role.
MC_DISCORD_WEBHOOK
The Discord webhook URL that notifications are posted to. Setting it is
what turns notifications on; without it none are sent. The notifications
section of the manifest selects which events are reported — instance
lifecycle, crashes, forced shutdowns, and backup results are all on by
default.
Instance Layout
An instance is a directory with mc.kdl at its root. All mc commands run
from that directory, and everything the instance needs lives under it:
myserver/
├── mc.kdl
├── mc.lock
├── .java/
├── .minecraft/
├── .tunnel/
│ ├── playit.toml
│ └── playitd.log
├── backups/
├── instance/
│ ├── eula.txt
│ ├── server.properties
│ ├── mods/
│ └── myserver/
└── temp/
Only one running server is allowed per instance directory; a second mc run
in the same directory refuses to start.
mc.kdl
The manifest describing the instance — the only file you author. See The Manifest Format.
mc.lock
The lockfile, written in KDL. It holds the mods resolved from the manifest, including their required dependencies, and the identity resolved for every player named in the manifest. The mod entries are rewritten from the manifest’s pinned versions on every start; the player entries are added by the player commands and by a start that meets a name not yet recorded.
.java/ and .minecraft/
Installed Java runtimes and Minecraft binaries, keyed by version, shared by every start of this instance. Safe to delete while the instance is stopped; whatever is missing is downloaded again on the next start.
.tunnel/
Present when the manifest has a tunnel section. Holds the installed
tunnel agents, keyed by version like .java/, the agent’s log in
playitd.log when its output is not shown in the terminal, and
playit.toml, the secret that links the agent to a tunnel provider account. The secret file is
created readable only by the owning user when the agent is first claimed,
and mc refuses to start if its permissions have been loosened. Deleting it
makes the next start claim a new agent; mc tunnel claim --force does the
same on demand. See Tunnels.
Instances created before tunnels existed have no /.tunnel entry in their
.gitignore; add one before committing.
backups/
The default destination for backup archives when local storage is used. The directory is dedicated to this instance’s backups; see Backups.
instance/
The live working directory of the Minecraft process. Notable contents:
eula.txt— generated from theeulakey in the manifest.server.properties— generated from the manifest on every start; manual edits are overwritten. Use thepropertiesblock of theserversection inmc.kdlinstead. When the file holds secrets, such as an RCON password, mc creates it readable only by the owning user and refuses to start if its permissions have been loosened.mods/— the installed mods. This directory is fully managed: mc adds and removes jars to match the lockfile, so a jar placed here by hand is deleted on the next start. Declare URL mods in the manifest instead.whitelist.json,banned-players.json,banned-ips.json,ops.json— the player lists, generated from theplayerssection of the manifest on every start. Changes the server writes to them on its own are replaced at the next start; usemc allow,mc ban, andmc opinstead.myserver/— the world, named after the instance’sname. Everything else Minecraft writes at runtime (logs, player data, and so on) also lives here and is left untouched by mc.
temp/
Scratch space for in-flight downloads and archives. Cleared when the instance starts; safe to delete while nothing is running.
Commands
- General Commands — the
mcbinary itself and its global options. - Manifest Commands — create and edit
mc.kdl:mc init,mc add,mc remove,mc update,mc allow,mc ban,mc op. - Instance Commands — operate the instance:
mc run,mc backup,mc restore. - Installation Commands — inspect and
pre-install runtimes and versions:
mc java,mc minecraft,mc tunnel.
General Commands
mc
mc [OPTIONS] <COMMAND>
The mc binary is a collection of subcommands; run one of the commands
documented in this chapter. Every command operates on the instance in the
current working directory — the directory containing mc.kdl.
Global options
These options are accepted by every command.
-v,--verbose— more detailed output. Repeat for more:-vprints informational messages,-vvdebug,-vvvtrace. The instance’s console log level follows this setting.-q,--quiet— do not print mc log messages.--color <WHEN>— control colored output:auto(the default),always, ornever.-h,--help— print help.-V,--version— print the mc version.
Exit status
mc exits with 0 on success and a non-zero code on failure.
mc run propagates the instance’s own exit code when the
instance ends abnormally.
mc help
mc help [COMMAND]
Prints help for mc or for the given command. Equivalent to passing
--help:
mc help init
mc init --help
The top-level help, mc help or mc --help, ends with a link to this
book.
mc completions
mc completions <SHELL>
Prints a completion script for the given shell to standard output. Accepted
shells: bash, elvish, fish, powershell, zsh.
Install it wherever the shell loads completions from. For example:
mc completions fish > ~/.config/fish/completions/mc.fish
mc completions bash > ~/.local/share/bash-completion/completions/mc
mc completions zsh > ~/.zfunc/_mc
The script describes the commands and options of the binary that generated it; regenerate it after upgrading mc.
Examples
mc completions fish > ~/.config/fish/completions/mc.fish
Manifest Commands
Commands that create or edit mc.kdl:
- mc init — create a new instance.
- mc add — add mods to the manifest.
- mc remove — remove mods from the manifest.
- mc update — update pinned mod versions.
- mc allow — manage the allow list.
- mc ban — manage the ban list.
- mc op — manage the operators.
mc init
mc init [OPTIONS] [PATH]
Creates a new instance: a mc.kdl manifest and a .gitignore. PATH
defaults to the current directory and is created if it does not exist. The
command refuses to run where a mc.kdl already exists.
The generated .gitignore excludes runtime state — the installed JDKs and
Minecraft binaries, the live server directory, scratch space, and run-time
lock files — so an instance can be versioned with git. The manifest and the
mc.lock lockfile are not excluded: commit them to make the instance
reproducible. An existing .gitignore is left untouched; a warning lists
any of these entries it lacks.
Options
--name <NAME>— the instance name. Defaults to the directory name.--eula— record your agreement to the Minecraft EULA in the generated manifest. Without it, the manifest is created witheula #falseand the instance will not start until you edit it.--preset <PRESET>— the shape of the generated manifest:vanilla— no mod loader and no mods.optimized— a mod loader plus performance mods. This is the default.technical— a mod loader plus performance mods and tools for technical play.
Presets pin the latest Minecraft release and compatible mod versions at the time the command runs; the generated manifest is a starting point to edit, not a fixed template.
Examples
mc init myserver
mc init --preset technical --eula
mc init myserver --name "smp" --preset vanilla
mc add
mc add [OPTIONS] <MOD_SLUG>...
Adds mods to the modrinth group of the manifest’s mods block. Each MOD_SLUG is the
mod’s identifier on the mod registry. The latest version compatible with the
configured Minecraft version and loader is looked up and pinned; the command
fails if a mod cannot be found for that combination.
A mod loader must be configured under minecraft before mods can be
added.
Changes take effect the next time the instance starts, which also installs any required dependencies — see Managing Mods.
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
Examples
mc add lithium
mc add carpet servux
mc remove
mc remove [OPTIONS] <MOD_SLUG>...
Removes mods from the manifest’s mods block, whichever group lists them. A slug that is not in
the manifest is reported and skipped.
The jars are uninstalled the next time the instance starts. A removed mod’s dependencies are not kept: anything no longer required disappears from the lockfile and is uninstalled along with it.
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
Examples
mc remove carpet
mc update
mc update [OPTIONS] [MOD_SLUG]...
Re-pins mods in the manifest to the latest version compatible with the configured Minecraft version and loader. With no arguments every mod is updated; otherwise only the named ones. Mods already at their latest version, and mods fetched from a URL (which carry no version), are skipped.
The new versions are installed the next time the instance starts.
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
Examples
mc update
mc update lithium carpet
mc allow
Manage the allow list: the players permitted to join when the allow list is enabled, which it is by default. See the Players guide for how the lists reach the server.
mc allow add
mc allow add [OPTIONS] <NAME>...
Adds players to the allow group of the manifest’s players section. Each
NAME is looked up to make sure the account exists and is recorded with
the account’s own casing. A player who is already allowed is skipped with a
warning; a player who is banned is refused until the ban is lifted.
When the instance is running and its remote console is reachable, the change is applied to it immediately. Otherwise it takes effect the next time the instance starts.
The list is still edited when allow-list in the server section is
#false, but a warning points out that anyone can join until it is
turned back on.
mc allow add Notch jeb_
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
mc allow remove
mc allow remove [OPTIONS] <NAME>...
Removes players from the allow list. Fails if a player is not on it. On a running instance, a removed player who is online is disconnected.
mc allow remove Notch
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
mc allow list
mc allow list [OPTIONS]
Prints the allowed players, one per line.
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
mc ban
Manage the ban list: players and addresses refused by the server. See the Players guide for how the lists reach the server.
mc ban add
mc ban add [OPTIONS] <NAME>...
mc ban add [OPTIONS] --ip <ADDRESS>...
Bans players, or with --ip, addresses. Player names are looked up to make
sure the account exists and are recorded with the account’s own casing. A
player who is already banned is an error. A player on the allow list is
removed from it, with a warning.
When the instance is running and its remote console is reachable, the ban is applied to it immediately and an online player is disconnected. A ban expiry cannot be applied live: the player stays banned until the next restart, when the expiry takes effect. Anything not applied live is reported with a warning.
Every player and address named in one command shares the same reason and expiry.
mc ban add Griefer --reason "stole the beacon"
mc ban add Griefer1 Griefer2 --for 7d
mc ban add --ip 203.0.113.7 --ip 203.0.113.8 --until 2026-12-31T00:00:00Z
Options
--ip <ADDRESS>— ban addresses instead of players. May be repeated.--reason <TEXT>— the reason shown to the banned player. Defaults to the server’s own wording.--until <DATE>— lift the ban at an RFC 3339 date.--for <DURATION>— lift the ban after a duration such as7d,12h, or30m. Cannot be combined with--until.--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
mc ban remove
mc ban remove [OPTIONS] <NAME>...
mc ban remove [OPTIONS] --ip <ADDRESS>...
Lifts bans on players, or with --ip, addresses. A player or address that
is not banned is skipped with a warning.
mc ban remove Griefer1 Griefer2
mc ban remove --ip 203.0.113.7
Options
--ip <ADDRESS>— unban addresses instead of players. May be repeated.--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
mc ban list
mc ban list [OPTIONS]
Prints the banned players, then the banned addresses, one per line with the reason, when the ban was issued, and when it expires.
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
mc op
Manage the operators: players granted server commands. Operators may join regardless of the allow list. See the Players guide for how the lists reach the server.
mc op add
mc op add [OPTIONS] <NAME>...
Makes players operators, or changes the settings of players who already are, with a warning. Player names are looked up to make sure the account exists and are recorded with the account’s own casing.
When the instance is running and its remote console is reachable, a new operator with the default settings is applied immediately. A custom level or the player limit bypass cannot be applied live and takes effect at the next restart, which is reported with a warning.
Every player named in one command gets the same settings.
mc op add Notch
mc op add jeb_ Dinnerbone --level 2 --bypass-player-limit
Options
--level <LEVEL>— the permission level, from1to4. Defaults to the server’sop-permission-levelproperty, which is4unless set in thepropertiesblock of theserversection.--bypass-player-limit— let the operator join when the server is full.--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
mc op remove
mc op remove [OPTIONS] <NAME>...
Removes operators. A player who is not an operator is skipped with a warning.
mc op remove Notch
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
mc op list
mc op list [OPTIONS]
Prints the operators, one per line with their effective permission level.
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.
Instance Commands
Commands that operate on the instance itself:
- mc run — start the instance.
- mc backup — back up the world.
- mc restore — restore the world from a backup.
mc run
mc run [OPTIONS]
Brings the instance in line with the manifest, then starts it. Anything
missing or out of date is installed first: the Java runtime, the Minecraft
binary, the mod loader, the mods (added, updated, and removed to match the
manifest), and the tunnel agent when a tunnel is configured. The generated
configuration files and player lists are rewritten from the manifest on
every start. A warning is printed for every key in the manifest’s
properties block that is not a known server property.
Only one running server is allowed per instance directory; a second
mc run refuses to start.
While the instance runs, mc supervises it, and scheduled backups fire when
enabled — see Backups. The instance’s console output
is hidden unless --server-logs is passed; it is always written to
instance/logs/ by the server itself. The console is not interactive; use
the remote console (RCON) for live administration.
With a tunnel section, the tunnel agent starts beside the instance and
is restarted if it stops on its own; the public address is printed at
startup. The agent’s output is hidden unless --tunnel-logs is passed, and
goes to .tunnel/playitd.log otherwise. The first start from a terminal prints a claim link to approve in a
browser and saves the resulting secret under .tunnel/. Without a terminal
and without a secret, mc run fails with instructions rather than waiting —
see Tunnels.
Stopping
Ctrl-C (or SIGTERM, e.g. from a service manager, or SIGHUP, e.g. when the
terminal that started the instance closes) asks the instance to save the
world and shut down, and waits for it to exit before returning. If the
instance hangs past a grace period, or a second signal arrives, it is forced
down immediately.
A scheduled backup caught in flight is cancelled: it discards its partial archive and never damages stored backups — see Backups.
mc does not restart a crashed instance; run it under a supervisor for that — see Running under systemd.
Exit status
When the instance ends abnormally, mc run fails and propagates the
instance’s exit code.
Options
--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.--lockfile-path <PATH>— path tomc.lock. Defaults to./mc.lock.--server-logs— show the instance’s console output in the terminal.--tunnel-logs— show the tunnel agent’s output in the terminal.
mc backup
mc backup [OPTIONS]
Archives the world and stores it in the storage target configured in the
backups section — see Backups. Works whether or
not scheduled backups are enabled.
The instance may be stopped or running. A running instance is reached over its remote console so the world is flushed to disk before it is archived; if the instance is running but the remote console is not available, the command refuses rather than capture a world that is still being written to. Only one backup can run at a time.
Named backups
By default the archive is named after the instance and a timestamp, and is
subject to the storage’s retention limit. With --name, the archive is
stored under the given name instead — for example
myserver_pre-update.tar.gz — and is kept forever: named backups never
count toward the retention limit and are never pruned. They appear in
mc restore --list alongside automatic backups.
Names may contain ASCII letters, digits, - and _. If a backup with the
same name already exists, mc asks before overwriting it (and refuses when it
cannot ask, such as in a script).
Cancelling
Ctrl-C cancels a backup in progress: the partial archive is discarded,
the instance’s auto-save is re-enabled, and the command fails with a
non-zero exit status. Stored backups are never affected by a cancelled
run.
Options
--name <NAME>— store the backup under a name and keep it forever instead of timestamping it and rotating it out.--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.
Examples
mc backup
mc backup --name pre-update
mc restore
mc restore [OPTIONS]
Replaces the world with one restored from a backup. The instance must be stopped.
The world being replaced is moved aside rather than deleted; if the restore
fails or is cancelled with Ctrl-C, the partially extracted world is
removed, the original is put back, and the command reports the failure. One
set-aside world is kept until the next restore replaces it.
A restore killed with no chance to clean up (power loss, SIGKILL) can leave
no world in place while the set-aside copy still exists. mc run refuses
to start in that state — instead of silently generating a fresh world — and
explains how to recover: run mc restore again, or mc restore --undo to
put the previous world back.
Undoing a restore
--undo puts the world set aside by the last restore back in place. When a
world is currently present the two are swapped — nothing is deleted, and
undoing again swaps back.
Options
--list— list the available backups instead of restoring. Shows both automatic (timestamped) and named backups;(latest)marks the newest automatic one.--backup <BACKUP>— the backup to restore, by the filename shown by--list. Defaults to the most recent automatic backup; named backups are only restored when passed explicitly.--undo— put the world set aside by the last restore back in place, swapping it with the current world.--manifest-path <PATH>— path tomc.kdl. Defaults to./mc.kdl.
Examples
mc restore --list
myserver_pre-update.tar.gz
myserver_2026-07-15_15-00-00.tar.gz (latest)
myserver_2026-07-14_15-00-00.tar.gz
mc restore
mc restore --backup myserver_pre-update.tar.gz
mc restore --undo
Installation Commands
Commands to inspect available versions and pre-install components.
mc run installs everything it needs automatically, so these
are mostly useful for exploring what is available and for provisioning
ahead of time:
- mc java — Java runtimes.
- mc minecraft — Minecraft versions and mod loaders.
- mc tunnel — tunnel agents.
mc java
Manage Java runtimes.
mc java list
mc java list
Lists the runtimes mc can install, as vendor@version descriptors. The one
marked (recommended) is the default used when the manifest does not
configure version under java.
mc java list
graal@25 (recommended)
graal@21
...
mc java install
mc java install [OPTIONS] <VERSION>
Downloads a runtime into the instance’s .java directory. VERSION is a
descriptor from mc java list; the version half may be omitted to take the
vendor’s recommended version. Fails if the runtime is already installed.
mc run installs the configured runtime automatically; this
command exists to provision one ahead of time.
Options
-p,--platform <PLATFORM>— install for a specific operating system instead of the current one.-a,--architecture <ARCHITECTURE>— install for a specific CPU architecture instead of the current one.
Examples
mc java install graal@25
mc java install corretto@21
mc minecraft
Manage Minecraft versions and mod loaders.
mc minecraft list
mc minecraft list [OPTIONS]
Lists Minecraft versions, most recent first. By default only the ten most recent releases are shown, with the latest release and latest snapshot tagged.
Options
--all— show every version instead of the ten most recent.-s,--snapshots— include snapshot versions.-b,--betas— include beta versions.-a,--alphas— include alpha versions.
mc minecraft list-loaders
mc minecraft list-loaders [OPTIONS]
Lists mod loader versions compatible with a Minecraft version, most recent first.
Options
-l,--loader <LOADER>— the loader to list versions for. Defaults tofabric.-m,--minecraft-version <VERSION>— the Minecraft version to list loader versions for. Defaults tolatest.--limit <LIMIT>— the number of results. Defaults to10.
mc minecraft install
mc minecraft install [OPTIONS] [VERSION]
Downloads a Minecraft binary into the instance’s .minecraft directory.
VERSION accepts the same values as version under minecraft in the manifest
(latest, latest-snapshot, or an exact version id) and defaults to
latest. Fails if that version is already installed.
mc run installs the configured version automatically; this
command exists to provision one ahead of time.
Options
-l,--loader <LOADER>— install the binary for a mod loader instead of the vanilla one, as anameorname@versiondescriptor (for examplefabric).
Examples
mc minecraft install
mc minecraft install --loader fabric
mc tunnel
Manage the tunnel agent that makes an instance reachable from outside the local network. See the Tunnels guide for the full picture.
mc tunnel list
mc tunnel list [OPTIONS]
Lists the tunnel agent versions mc can install, most recent first. The one
marked (latest) is what provider under tunnel resolves to when its version
half is omitted or set to latest.
mc tunnel list
1.0.10 (latest)
1.0.9
...
Options
--limit <LIMIT>— the number of results. Defaults to10.
mc tunnel install
mc tunnel install [OPTIONS] [PROVIDER]
Downloads a tunnel agent into the instance’s .tunnel directory. PROVIDER
accepts the same values as provider under tunnel in the manifest, a name or
name@version descriptor, and defaults to playit. Fails if that version is
already installed.
mc run installs the configured agent automatically; this
command exists to provision one ahead of time.
Options
-p,--platform <PLATFORM>— install for a specific operating system instead of the current one.-a,--architecture <ARCHITECTURE>— install for a specific CPU architecture instead of the current one.
Examples
mc tunnel install
mc tunnel install playit@1.0.9
mc tunnel claim
mc tunnel claim [OPTIONS]
Links the instance’s tunnel agent to an account with the tunnel provider.
The command prints a link; opening it in a browser while signed in to the
provider approves the agent, after which the agent secret is saved to
.tunnel/playit.toml, readable only by the owning user. The link expires
after a few minutes.
mc run performs the same claim on its own when the instance
starts from a terminal without a secret file, so this command is only needed
to claim ahead of time, for example before deploying under a service manager,
or to replace an existing secret.
Options
-f,--force— replace an existing secret with a fresh claim. The previous agent stays registered with the provider until it is removed there.
Examples
mc tunnel claim
Claiming tunnel agent, approve it at https://playit.gg/claim/... with your playit.gg account
Claimed tunnel agent secret saved to .tunnel/playit.toml