MCStatusBot is gone. Here's a 40-line script that keeps your Minecraft server's status in Discord - DEV Community

DEV Community

Ridh Grg for MineOps

Posted on

MCStatusBot is gone. Here's a 40-line script that keeps your Minecraft server's status in Discord

MCStatusBot, the bot a lot of Discord communities used to show whether their Minecraft server was online, went offline on 1 September 2026. If your #server-status channel has been frozen since then, this post gets it working again with a short Python script and a Discord webhook. No bot account, no open ports.

The script keeps one message in the channel and edits it every minute, so the channel never fills up with status posts:

🟢 play.example.com is online: 3/20 players
checked 14:02 UTC

What you need

  • Python 3.9 or newer on any machine that's always on (it doesn't have to be the server).
  • The mcstatus library: pip install mcstatus
  • A Discord webhook: Server Settings → Integrations → Webhooks → New Webhook, pick the channel, Copy Webhook URL.

The script

Save this as mc_discord_status.py:

#!/usr/bin/env python3
"""Keep one Discord message showing whether a Minecraft server is up."""
import json
import os
import pathlib
import urllib.error
import urllib.request
from datetime import datetime, timezone

from mcstatus import JavaServer

SERVER = os.environ["MC_ADDRESS"]           # e.g. play.example.com or 1.2.3.4:25565
WEBHOOK = os.environ["DISCORD_WEBHOOK"]     # the URL you copied from Discord
STATE = pathlib.Path(os.environ.get("STATE_FILE", "~/.mc-status-message")).expanduser()


def check():
    try:
        status = JavaServer.lookup(SERVER, timeout=5).status()
        return f"🟢 **{SERVER}** is online: {status.players.online}/{status.players.max} players"
    except Exception:
        return f"🔴 **{SERVER}** is offline"


def send(method, url, body):
    req = urllib.request.Request(
        url, data=json.dumps(body).encode(), method=method,
        headers={"Content-Type": "application/json", "User-Agent": "mc-status/1.0"},
    )
    with urllib.request.urlopen(req, timeout=10) as resp:
        return json.load(resp)


def main():
    stamp = datetime.now(timezone.utc).strftime("%H:%M UTC")
    body = {"content": f"{check()}\n-# checked {stamp}"}
    message_id = STATE.read_text().strip() if STATE.exists() else None
    if message_id:
        try:
            send("PATCH", f"{WEBHOOK}/messages/{message_id}", body)
            return
        except urllib.error.HTTPError as err:
            if err.code != 404:      # 404: someone deleted the message, post a new one
                raise
    message = send("POST", f"{WEBHOOK}?wait=true", body)
    STATE.write_text(message["id"])


if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

How it works:

  1. JavaServer.lookup(...).status() does the same "server list ping" your Minecraft client does when it shows a server in the multiplayer list. It follows SRV records, so a domain without a port works.
  2. The first run posts a message with ?wait=true, which makes Discord return the message, and saves its id to a small state file.
  3. Every later run edits that message (PATCH .../messages/<id>). If someone deletes it, Discord answers 404 and the script posts a fresh one.
  4. -# is Discord's small grey "subtext" formatting, used here for the time of the last check.

Run it every minute

Try it once by hand:

export MC_ADDRESS="play.example.com"
export DISCORD_WEBHOOK="https://discord.com/api/webhooks/..."
python3 mc_discord_status.py
Enter fullscreen mode Exit fullscreen mode

Then add it to cron with crontab -e:

* * * * * MC_ADDRESS=play.example.com DISCORD_WEBHOOK=https://discord.com/api/webhooks/... /usr/bin/python3 /home/you/mc_discord_status.py
Enter fullscreen mode Exit fullscreen mode

Treat the webhook URL like a password: anyone who has it can post in that channel.

Where a ping falls short

A ping only sees what the server answers from outside. It can't tell a crash from a restart you did on purpose, it won't notice a server that's up but lagging, and a run that fails silently looks the same as "online" until someone checks.

That's the gap I built MineOps to fill for servers you run on your own Linux or Mac machine. A small agent next to the server (it only connects out, so no ports to open) keeps a live status message in Discord, marks planned stops and maintenance as planned, and sends separate alerts to your staff channel for crash loops, low TPS, a full disk or a failed backup. Two servers are free.

If you only need the green dot back in #server-status, the script above is all you need.

Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft.

Top comments (0)