Skip to content

Putting a server on the public list

A server announces itself to the public list at kcd-mp.com once a minute, and every launcher’s Servers tab shows what the list has. Nothing has to be registered, but the list only shows a server players can join: when an announcement comes in, the list asks the server what a launcher asks it - over its UDP port, at the address it would list - and shows it once it answers, a few seconds after its first announcement. It keeps asking every half minute: a server that stops answering is off the list within a minute and back as soon as it answers again, and one that stops announcing is gone three minutes after its last announcement. A server whose own work stops (nobody could join it) stops announcing too, and says so in its log. The settings are [master] and [server] in server.toml (Server configuration).

Announced but not on the list? The list could not reach the server: the UDP port is closed or not forwarded (section 1), or the list sees another address than the one players should use (section 2). The server’s console says so: master: on the public list as <address> once it is listed, and otherwise master: the list cannot reach this server at <address> with the reason - check that the address is the one players use. Test from outside your network with the launcher’s Direct connect - the list asks exactly what its Query button asks. A server in your own network answers your launcher even when nobody outside can reach it, so seeing it in your own launcher proves nothing.

The server takes one UDP port, [server] port (7777 by default). Open it on the machine’s firewall and, behind a home router, forward it to the machine - UDP, not TCP. Two servers on one machine take two ports.

The same number over TCP answers the server’s status page: http://<address>:7777/ gives its name, level, game mode, version, the players and their names, the slots, whether it wants a password, its uptime and the world’s time as JSON - for a hosting panel, an uptime monitor or a website that lists your server. A server nobody can join at that moment answers 503. Open TCP too if you want it reachable from outside; [server] http_status = false switches it off.

The list shows a server under the address it sees the announcement come from - the machine’s public IPv4 address (the server announces itself over IPv4), which is right for a server on a rented box or behind a plain home connection. When it is not - a server that should be found under a hostname, or one behind an address the list cannot see - name it. A server that players reach on another port than its own (a tunnel such as playit.gg hands out one) gives that port too, "host:port". Leave it "" unless you need it: a fixed address goes stale when a home connection’s address changes, and two servers must never name the same address and port - the list keeps one row for both (the console warns about it):

[master]
url = "https://kcd-mp.com/server-list" # the public list; "" = announce nowhere (a private server)
interval_seconds = 60 # how often
public_address = "" # "" = the address the list sees; else a hostname or an address, with ":port" for a tunnel's port

url = "" keeps a server off the list altogether - a test server, a private one for friends who connect by address. The environment variables KCDMP_MASTER_URL and KCDMP_MASTER_ADDRESS stand in for the two addresses when set, and the command line’s --master / --master-address beat both.

The list carries the server’s name, its level, the players on it against max_players, the game mode’s name, the server’s version and whether a password is needed:

[server]
name = "KCD:MP dev server" # the name in the list and in the welcome
motd = "" # a line shown to every joining player
password = "" # players must type it to join; "" = open
max_players = 32
level = "klaster" # klaster, trosecko or kutnohorsko

A click on a server in the launcher opens its details beside the list: what it runs, and what you tell players about it - a description, your website, your Discord, a few tags and the language spoken there. The public list carries them too:

[server]
description = "Medieval roleplay at Trosky.\nWhitelist on our Discord." # \n starts a new line; 1000 characters at most
website = "https://example.org"
discord = "https://discord.gg/abc123"
tags = ["roleplay", "whitelist"] # up to 8
language = "en"

Your tags show beside the server’s name in the list and in its details, and players can type one into the list’s filter. They are the only tags a server shows: the launcher adds none of its own.

A player picks the server in the launcher’s Servers tab (or types its address under Direct connect), gives the password if there is one, and the launcher boots their game onto the server’s level. A client and a server only play together on the same protocol number - the release notes give it - so a server is updated together with the client release; [server] build_hash can further require one game build.

The list is also a page on the website, kcd-mp.com/server-list, with the same entries, the fullest servers first - as in the launcher, which shows only the servers that answer it.

A link to kcdmp://connect/<address>:<port> opens the player’s launcher on your server’s details, where one click joins:

<a href="kcdmp://connect/play.example.org:7777">Join our server</a>

The address is the one players use (the list’s), with the port; without one the launcher takes 7777. The link carries nothing else - no password, no player name: a server with a password asks for it in the launcher. Players get the link type with the launcher, the first time its window opens; a player who never started it gets nothing from the click, so put the download beside the button. Browsers ask once before they open the launcher. Discord shows such a link as plain text - post your server’s address there, or a page of yours with the button.

  • Admins: the game mode names them (Setting up: the shipped freeroam takes the KCDMP_ADMINS names); the server keeps no accounts and no admin list. [commands] public names the built-ins anyone may use, disabled switches some off.
  • Accounts: a name belongs to nobody as far as the server is concerned. A game mode with a database behind it (Databases) gives players a /register and a /login and keeps their things between visits; the shipped freeroam does exactly that once [gamemode.database] is set.
  • Bans: /kickban <player> [minutes] (5 minutes when no number is given) and /unban in the chat; a ban for good, or any rule of your own, is a game mode’s (Ban). The bans live in the server’s own database (data/server.db) and survive a restart. A name ban is only as strong as the name; the address ban is the one that holds.
  • Cheating: the server owns every player’s health, stamina, items and position - it judges what the clients report against its own record, and the world data sharpens that judgement: the terrain and the collision geometry catch a player through a wall or in the air, the tables make a hit what the game says it is, and the audit ([audit]) catches items a player cannot explain and a character’s levels, experience, perks, nourishment, energy or carried weight that nothing explains (the progression check). It starts in observe, which only logs - read the log for a while, then switch it to enforce (a cheat the server can prove, a game that ignores an order or goes silent, gets the [audit] action in either mode, a kick by default).