Back to Features
For MUD Server Owners

GMCP Integration Guide

MudMonster supports the Generic MUD Communication Protocol (GMCP) — a Telnet sub-negotiation channel for structured data exchange between MUD servers and clients. This guide explains what MudMonster advertises, what packages it reads, and how to implement server-side GMCP support so your players get the best experience.

What MudMonster Advertises

When GMCP negotiation succeeds, MudMonster sends a Core.Supports.Set message advertising which GMCP packages it can consume:

Core.Supports.Set [
  "Char 1",
  "Char.Skills 1",
  "Char.Status 1",
  "Char.Vitals 1",
  "Char.Worth 1",
  "Comm 1",
  "Comm.Channel 1",
  "Room 1",
  "Room.Info 1"
]

Your server should check this list and only send the packages that have been requested. Sending unsolicited GMCP data may be silently ignored.

Core.Hello

Immediately after GMCP negotiation, MudMonster identifies itself with a Core.Hello message:

Core.Hello { "client": "MudMonster", "version": "1.0" }

You can use this to enable MudMonster-specific features or customise the data you send. The client value will always be "MudMonster".

Wire Format — How to Send a GMCP Packet

GMCP uses Telnet sub-negotiation. A packet is wrapped in: IAC SB GMCP <package> SP <json> IAC SE. Any 0xFF (IAC) bytes inside the JSON payload must be escaped by doubling them.

/* Telnet constants */
#define IAC  255   /* 0xFF */
#define SB   250   /* 0xFA — begin sub-negotiation */
#define SE   240   /* 0xF0 — end sub-negotiation  */
#define GMCP 201   /* 0xC9 — GMCP option           */

/*
 * Send a GMCP packet to the client.
 *   package  — e.g. "Room.Info"
 *   json     — e.g. {"vnum":"1234","name":"Town Square"}
 *
 * Wire layout:
 *   IAC SB GMCP <package-bytes> SP <json-bytes> IAC SE
 *
 * Any 0xFF byte inside <json-bytes> must be sent as 0xFF 0xFF.
 */
void send_gmcp(int fd, const char *package, const char *json) {
    /* header */
    unsigned char header[] = { IAC, SB, GMCP };
    write(fd, header, 3);

    /* package name */
    write(fd, package, strlen(package));

    /* space separator */
    write(fd, " ", 1);

    /* json body — escape IAC bytes */
    for (size_t i = 0; i < strlen(json); i++) {
        unsigned char c = (unsigned char)json[i];
        write(fd, &c, 1);
        if (c == IAC) write(fd, &c, 1);  /* escape 0xFF */
    }

    /* footer */
    unsigned char footer[] = { IAC, SE };
    write(fd, footer, 2);
}

Room.Info — Minimap Overlay

Room.Info drives MudMonster's GMCP minimap overlay. Send this packet every time the player moves to a new room.

Room.Info {
  "area":    "Seringale",
  "name":    "Bakery",
  "terrain": "inside (indoors)",
  "vnum":    "4518",
  "symbol":  "F",
  "exit":    { "south": "4647", "up": "4519" },
  "map":     "`8+`2        \n`8|        \n..."
}
  • area — zone or area name, shown in the map header
  • name — room display name, shown in the map footer
  • terrain — terrain type string (optional)
  • vnum — unique room identifier, sent as a string
  • symbol — single character used to represent this room type on the map
  • exit — object mapping direction strings to destination room vnums (strings). Supported directions: north, south, east, west, up, down
  • map — optional pre-rendered ASCII map string with embedded color codes (see Color Codes below). Lines are separated by \n. When present, MudMonster renders this map directly in the overlay instead of computing one from exit data. The player's current position is typically marked with `!@.

Map Color Codes

MudMonster supports both ANSI escape sequences and backtick color codes in map strings. Backtick codes take the form `N where N is a single character:

Code Color Notes
`0Light pink
`1Red
`2Green
`3Yellow
`4Dark blue
`5Purple
`6Cyan
`7White
`8Dark gray
`9Bright red
`!RedPlayer position marker color
`@Bright greenTypically used as the @ player-position glyph
`&White
`^Teal
`$Blue-purpleBold
`%Deep pinkBold
`#Bright yellowBold
``Escaped backtick — renders as a literal ` character

Char.Vitals — Vitals Bar

Char.Vitals drives the HP, MP, and movement bars displayed in MudMonster's vitals overlay. Send this whenever any vital changes.

Char.Vitals {
  "hp":      "219",
  "maxhp":   "219",
  "mana":    "158",
  "maxmana": "170",
  "move":    "225",
  "maxmove": "225",
  "wait":    "0"
}

All values may be sent as either strings or integers — MudMonster coerces them to numbers internally. The wait field is received but not currently displayed.

MudMonster accepts the following field name aliases for compatibility with different MUD codebases:

Canonical field Accepted aliases Meaning
hp / maxhp health / maxhealth · hits / maxhits Hit points
mp / maxmp mana / maxmana · magic / maxmagic Mana / magic points
mv / maxmv move / maxmove · moves / maxmoves · sp / maxsp · stamina / maxstamina Movement / stamina points

Only hp and maxhp are required. Omit mp/mv fields if your game does not use them — MudMonster only shows bars for the stats it receives.

Char.Worth — XP Progress Bar

Char.Worth drives MudMonster's XP progress bar — a slim bar above the vitals display showing real-time progress toward the next rank. Send this whenever the character's experience changes.

Char.Worth {
  "xp":    12500,
  "maxxp": 10000,
  "xptnl": 20000
}
  • xp — current accumulated experience
  • maxxp — XP at the start of the current level (the previous threshold). Used as the lower bound for progress calculation.
  • xptnl — XP at the end of the current level (next rank threshold). When xp reaches this value, MudMonster plays a rank-up animation.

Progress is calculated as (xp - maxxp) / (xptnl - maxxp). All values may be sent as strings or integers.

Char.Status — Character Identity

Char.Status provides the player's character name, level, and class. Send this on login and whenever the character's level or class changes.

Char.Status {
  "name":  "Gandalf",
  "level": 42,
  "class": "Mage",
  "race":  "Elf"
}

Only name is required. level, class, and race are optional and stored for future display surfaces.

Char.Group — Group Member Vitals

Char.Group delivers health and mana percentages for each member of the player's group. MudMonster stores this data for use in future group-display overlays. Send this whenever group membership or member vitals change.

Char.Group [
  { "name": "Gromglom", "hp": "100", "mp": "91" },
  { "name": "Serafina", "hp": "72",  "mp": "55" }
]
  • name — character name of the group member
  • hp — current HP as a percentage (0–100), sent as a string or integer
  • mp — current mana as a percentage (0–100), sent as a string or integer

Note: Group display UI is planned. The data is captured now for forward compatibility — your players will benefit automatically once the feature ships.

Char.Affect — Active Effects

Char.Affect lists the spells and effects currently active on the character. MudMonster stores this data for future display. Send a full replacement array whenever any effect is added, removed, or its duration changes.

Char.Affect [
  { "name": "chii",          "dur": "3 hours"  },
  { "name": "shadow tactics","dur": "-1 hours" }
]
  • name — display name of the effect or spell
  • dur — duration string (e.g. "3 hours"). A value of "-1 hours" conventionally means the effect is permanent or has no time limit.

Note: Active effects UI is planned. Sending this data now ensures your players get the overlay automatically when it ships.

Room.World — In-Game Time

Room.World provides the current in-game hour. MudMonster stores this data for future display surfaces. Send this packet each time the in-game hour advances.

Room.World { "hour": "14" }
  • hour — current in-game hour (0–23), sent as a string or integer

Char.Base — Channel Text

Some servers send channel speech through Char.Base rather than Comm.Channel. MudMonster receives and stores this payload for future channel panel support.

Char.Base {
  "channels": "An apprentice monk says 'Hello world!'"
}
  • channels — the channel message as a raw string. May contain MUD color codes (backtick format).

Comm.Channel — Structured Channel Messages

Comm.Channel delivers structured channel message data for use in MudMonster's dedicated channel panel (in development). Send this whenever a channel message is broadcast. This is preferred over Char.Base when available, as it provides speaker and channel metadata separately.

Comm.Channel {
  "chan":   "gossip",
  "msg":    "Hello world!",
  "player": "Gandalf"
}
  • chan — channel identifier (e.g. "gossip", "ooc", "shout")
  • msg — the message text, stripped of ANSI escape codes
  • player — the speaker's character name

Note: The channel panel feature is planned and channel data is captured now for forward compatibility. Your players will benefit automatically once the panel ships.

Testing Your Integration

MudMonster includes a built-in GMCP debug mode to help you verify your server's output.

Enable GMCP debug logging

  1. Open the MudMonster app and connect to your MUD.
  2. Tap the hamburger menu (top-right) and go to Settings.
  3. Enable GMCP Debug Mode.
  4. Raw GMCP packets will appear in the terminal prefixed with [GMCP].

Common issues

  • Packets not arriving — make sure your server completes GMCP Telnet negotiation (IAC WILL GMCP / IAC DO GMCP handshake) before sending any sub-negotiation data.
  • Minimap not updating — confirm that Room.Info is in Core.Supports.Set and that you are sending either a map string or exit data with each room change.
  • Vitals bar missing — MudMonster only shows the bar after receiving the first Char.Vitals packet. Make sure you send it on login, not just on change.
  • XP bar not appearing — confirm Char.Worth is in your Core.Supports.Set response and that maxxp and xptnl are different values (a zero-width range hides the bar).
  • JSON parse errors — ensure the JSON payload is valid UTF-8 and that any 0xFF bytes are doubled. Stray ANSI escape sequences inside JSON strings will break parsing.
  • Negotiation timing — do not send Core.Supports.Set or room/character data until after the client has responded to your IAC DO GMCP. Wait for the Core.Hello packet from MudMonster as your signal.

Package Summary

Package When to send Powers
Room.Info Every room change Minimap overlay
Char.Vitals Any vital changes; always on login HP / MP / MV vitals bar
Char.Worth Any XP changes; always on login XP progress bar + rank-up animation
Char.Status Login; level or class change Character identity (future display)
Char.Group Group change; member vitals change Group panel (planned)
Char.Affect Any effect added, removed, or ticked Active effects display (planned)
Room.World Each in-game hour advance In-game clock (planned)
Comm.Channel Each channel broadcast Channel panel (planned)
Char.Base Channel speech (alternative to Comm.Channel) Channel panel (planned)

Further Resources