Standards:MUD Client Media Protocol
MUD Client Media Protocol (MCMP)
A Standard for Loading, Playing and Stopping Media Files with MUD Clients over GMCP
Version 2 is a proposal, open for discussion.
- Everything on this page outside the boxes marked Proposed for version 2 is version 1, which is unchanged. Version 1 clients and servers can keep reading this page as before.
- Version 2 adds only optional keys and messages, so a version 1 client keeps working with a version 2 game:
- pan and direction on Client.Media.Play place a sound to the left or right, or in a direction such as north or behind.
- Client.Media.Update moves a sound that is already playing, or changes its volume.
- Client.Media.Listener tells the client which way the player faces, for games that have a facing.
- Please join the discussion in the MUDstandards channel of the MUD Discord server, and see the open questions below.
Status of this Memo
This memo describes the addition of a standardized namespace of the Generic Mud Communication Protocol (GMCP) telnet sub-negotiation protocol (201) that provides syntax and usage guidance for sending JSON formatted messages from game servers to text-based game clients to load, play and stop media files.
Overview and Rationale
With renewed interest in the MUD genre of gaming, expectations are high to provide sight and sound content that competes for audience with other gaming platforms. The purpose of the MUD Client Media Protocol (MCMP) is to establish a method of delivering media, such as game sounds, background music and video snippets, to text-based game clients via their widely accepted messaging platform, GMCP, which uses JSON as its data-interchange format. The intended return for introducing this protocol is to improve the MUD gaming experience and accessibility through standardized messaging between game servers and game clients. MUD Client Media Protocol (MCMP) is inspired by its predecessor Mud Sound Protocol (MSP).
Overview of the GMCP (201) Sub-negotiation Protocol
To recap, the GMCP protocol is a bidirectional telnet sub-negotiation protocol (See RFC 854) which fulfills the following conditions:
- GMCP is separated into several ‘namespaces’, which may be enabled or disabled by the client at any time. The ‘Core’ namespace is always enabled and may not be disabled. Namespaces should consist of case-insensitive alphabetical characters and stop characters (. - ASCII 46/0x2E), representable as [A-Za-z.].
- GMCP messages consist of the namespace and a command (case insensitive alpha characters) delineated by a stop character, and optionally a space character and JSON-encoded payload.
- GMCP messages may be sent by both the client or server at any time with no warning.
Update to namespace: Client.* for Client.Media
We are proposing an addition to the Client.* meta-namespace for Client.Media. This serves the purpose of reserving this namespace for handling game client media operations and supporting future expansion and integration.
Video Demonstration of Client.Media
Specification for Client.Media
The Client.Media family of GMCP packages provide a way for games to send sound, music and video events. GMCP media events are sent in one direction: from game server to to game client. Media files may be downloaded manually by the user and/or automatically via the game client. Game clients should advertise to servers that Client.Media is supported with a Core.Supports message from game client to server.
Core.Supports.Set ["Client.Media 1", ...]
Proposed for version 2: advertising and compatibility
- A client that supports version 2 advertises it with the version number, as other GMCP packages do when they grow:
Core.Supports.Set ["Client.Media 2", ...]
- A server that checks only for the package name, Client.Media, keeps working with both versions.
- Version 2 adds only optional keys and new messages. A version 1 client ignores keys it does not know and plays the sound as before, and ignores messages it does not know. So a server may send version 2 keys to every client.
- A server should check for version 2 before its gameplay depends on hearing where a sound comes from, such as an audio-only puzzle.
- Version 2 adds no new values for "type". Some version 1 clients drop a whole message whose "type" they do not know.
Commands - Server
Due to the limitations for legacy gaming platforms supporting all JSON data types, such as boolean (true and false), game clients should support parsing of values within the Client.Media namespace also as strings (surrounded by quotes).
Client.Media.Default
- Package: Client.Media.Default
- Purpose: Identify to the game client a default URL directory to load media files from an external resource.
- Guidance: For games that automatically download media files, perform a Client.Media.Default GMCP event once upon player login.
Syntax:
Client.Media.Default {"url": "hxxps://www.example.com/media/"}
Usage:
| Required | Key | Value | Purpose |
|---|---|---|---|
| Yes | "url" | <url> |
|
Note:
Some examples are shown here.
Client.Media.Load
- Package: Client.Media.Load
- Purpose: Load media files from an external source.
- Guidance: For games that automatically download media files and have the capability to cache with the game client.
Syntax:
Client.Media.Load {
"name": "sword1.mp3",
"url": "hxxps://www.example.com/media/"
}
Usage:
| Required | Key | Value | Purpose |
|---|---|---|---|
| Yes | "name" | <file name> |
|
| Maybe | "url" | <url> |
|
Note:
Some examples are shown here.
Client.Media.Play
- Package: Client.Media.Play
- Purpose: Play media files.
- Guidance: Game clients could choose whether to play only one media file at one time or multiple files at one time.
Syntax:
Client.Media.Play {
"name": "80_Blacksmith_Shoppe.mp3",
"url": "hxxps://www.example.com/media/",
"type": "music",
"tag": "environment",
"volume": 25,
"fadein": 5000,
"fadeout": 7000,
"start": 1000,
"finish": 20000,
"loops": 3,
"priority": 60,
"continue": true,
"key": "area-background-music",
"caption": "Blacksmith Hammering"
}
Usage:
| Required | Key | Value | Default | Purpose |
|---|---|---|---|---|
| Yes | "name" | <file name> |
| |
| Maybe | "url" | <url> |
| |
| No | "type" | "sound", "music" or "video" | "sound" |
|
| No | "tag" | <tag> |
| |
| No | "volume" | 1 to 100 | 50 |
|
| No | "fadein" | <msec> |
| |
| No | "fadeout" | <msec> |
| |
| No | "start" | <msec> | 0 |
|
| No | "finish" | <msec> | 0 |
|
| No | "loops" | -1, or >= 1 | 1 |
|
| No | "priority" | 1 to 100 |
| |
| No | "continue" | true or false | true |
|
| No | "key" | <key> |
| |
| No | "caption" | <text> |
|
Note:
To support players with hearing impairments or who prefer captioned media, the caption field may be used to provide contextual and caption-style text. For best practices, see Captioning Key: Sound Effects and Music.
Note:
Some examples are shown here.
Proposed for version 2: where a sound comes from
Two new optional keys on Client.Media.Play. A version 1 client ignores them and plays the sound as it always has.
Syntax:
Client.Media.Play {
"name": "door-creak.wav",
"key": "north-door",
"volume": 60,
"direction": "north",
"caption": "a door creaks"
}
Usage:
| Required | Key | Value | Default | Purpose |
|---|---|---|---|---|
| No | "direction" | a direction word, or degrees from 0 to 359 | none: the sound plays as recorded, as in version 1 |
|
| No | "pan" | -100 to 100 | none: the sound plays as recorded |
|
- With no facing, north is ahead and east is to the right, like a map with north at the top. A game whose player has a facing can say so with Client.Media.Listener.
- Relative words are always relative to the player and ignore the facing: "ahead" is 0°, "right" 90°, "behind" 180° and "left" 270°. They are for games without compass exits.
- A word the client does not recognise is ignored, and the sound plays as with no direction, so a game can pass any exit name. For a sound through an exit with no compass direction, such as "in" or a portal, say where it comes from in "caption", e.g. "footsteps from the shop".
- Each client renders as much as it can:
- A client with 3D audio, such as on headphones, places the sound in its direction, including behind, above and below. A compass direction's angle from the player is its bearing minus the facing.
- A stereo client turns a direction into pan = 100 × sin(direction): east is fully right, west fully left, and north and south are centred. "up" and "down" stay centred.
- A client with no panning plays the sound centred, as in version 1.
- A placed sound is heard from one point: a stereo recording is mixed to one point first. A sound with neither "direction" nor "pan" plays as recorded, stereo image included.
- When a message has both "pan" and "direction", a 3D client uses "direction" and a stereo client uses "pan". That lets a game tune the result for each kind of client.
- Captions: a version 2 client adds the direction to the caption it shows, e.g. "a door creaks (north)", so that where a sound comes from never depends on hearing it.
- Music and video: these keys are for sounds. Clients may ignore "direction" and "pan" on "music" and "video".
- "pan" uses the same -100 to 100 scale as MUSHclient's PlaySound, and the same key as the Mongoose MOO web client's MCMP extension, so a game sending "pan" today is understood by more than one client.
Client.Media.Update
Proposed for version 2: a new message
- Package: Client.Media.Update
- Purpose: Move a sound that is already playing, or change its volume, without restarting it.
- Guidance: Covers sounds that travel, such as footsteps coming up from behind or an arrow in flight: send a few updates as the sound moves. A version 1 client ignores this message, so the sound stays where it started.
Syntax:
Client.Media.Update {
"key": "dragon",
"direction": "south",
"volume": 80,
"duration": 2000
}
Usage:
| Required | Key | Value | Default | Purpose |
|---|---|---|---|---|
| Maybe | "key" | <key> |
| |
| Maybe | "name" | <file name> |
| |
| Maybe | "tag" | <tag> |
| |
| No | "type" | "sound", "music" or "video" | any |
|
| No | "volume" | 1 to 100 | unchanged |
|
| No | "direction" | as on Client.Media.Play | unchanged |
|
| No | "pan" | -100 to 100 | unchanged |
|
| No | "duration" | <msec> | 0 |
|
- Straight after a Play: an update may follow its Play at once, before the file has loaded or downloaded. It applies once the sound plays.
- Captions: a client does not caption an update. The Play was captioned, and an update only changes how that sound is heard.
Client.Media.Listener
Proposed for version 2: a new, optional message
- Package: Client.Media.Listener
- Purpose: Tell the client which way the player faces, so that compass directions are heard relative to it.
- Guidance: Most games never send it. Ships, vehicles and games that say "to your left" would. A version 1 client ignores it.
Syntax:
Client.Media.Listener {"facing": "east"}
Usage:
| Required | Key | Value | Default | Purpose |
|---|---|---|---|---|
| Yes | "facing" | a compass word, or degrees from 0 to 359 | "north" |
|
- A facing lasts for the connection: after a reconnect the client faces north again, or the player's own choice where the client offers one, until the game sends Client.Media.Listener again.
Client.Media.Stop
- Package: Client.Media.Stop
- Purpose: Stop playing media files.
- Guidance: An empty body will stop all media.
Syntax:
Client.Media.Stop {
"name": "city.mp3",
"type": "music",
"tag": "environment",
"priority": 60,
"key": "area-background-music",
"fadeaway": true,
"fadeout": 7000
}
Usage:
| Required | Key | Value | Purpose |
|---|---|---|---|
| No | "name" | <file name> |
|
| No | "type" | "sound", "music" or "video" |
|
| No | "tag" | <tag> |
|
| No | "priority" | 1 to 100 |
|
| No | "key" | <key> |
|
| No | "fadeaway" | true or false |
|
| No | "fadeout" | <msec> |
|
Note:
Some examples are shown here.
Open questions for version 2
These are open for discussion in the MUDstandards channel of the MUD Discord server:
- Height in 3D: at what angle should a 3D client place "up" and "down"? Directly overhead and underfoot (90°) are hard to hear on headphones; audio games usually use 45° to 60°.
- Left out on purpose:
- "distance": "volume" stays the one control of loudness, so a sound is never made quieter twice.
- Separate ids for each playing sound: a key already names one sound, so each copy that should move on its own is given its own key.
- Attaching a position to a later Play: a game can add "direction" to the Play it sends.
- Height in degrees: "up" and "down" are how MUDs describe height.
- A separate package wrapping Client.Media.Play: a version 1 client ignores the new keys, so a game sends one message to every client.
- Coordinates, rooms and reverb: these need an agreed frame of reference (which axis is north, which way is up, and what the units are), and clients that already use coordinates disagree on it. They could be a later version.
Best Practices for Server Implementors
In keeping with best practices widely adopted in modern web applications and browsers, server-side implementors of the `Client.Media` protocol are advised to consider the following:
- Avoid Autoplay Before User Interaction: Media files should not be played immediately upon client connection, especially before the user has had an opportunity to interact with the game environment. Autoplaying media without user initiation may be blocked or suppressed by some clients, particularly web-based ones, and can create a disruptive experience for players.
- Use Secure Media URLs: Whenever possible, media files should be served via secure HTTPS URLs. Serving media over insecure HTTP links may trigger mixed content security warnings or result in blocked requests in web-based clients or modern operating systems with strict security policies.
Notes for Web Client Developers
Developers of web-based Mud clients should be aware of the following constraints that may impact media playback behavior:
- Most browsers impose restrictions on media autoplay unless the user has interacted with the page. This may prevent `Client.Media.Play` messages sent immediately after connection from functioning as intended.
- Serving media over non-HTTPS URLs may result in blocked requests or mixed content warnings, depending on the browser and hosting setup.
These limitations are imposed by browser security models and are not under the control of the game server or client developers. Where possible, client developers may want to inform users or log these situations for debugging.
Proposed for version 2: panning in a browser
- A browser can pan media from another site only when that site sends CORS headers; otherwise the panned sound comes out silent. This is one reason clients may ignore "pan" and "direction" on music, which is often streamed from elsewhere.
Versions
- Version 1.0: Initial specification.
- Version 1.0.1: fadein, fadeout and start added to Client.Media.Play by Mike Conley (mike.conley[at]stickmud.com) on 22-DEC-2021.
- Version 1.0.2: finish added to Client.Media.Play and fadeaway and fadeout added to Client.Media.Stop by Mike Conley (mike.conley[at]stickmud.com) on 10-DEC-2023.
- Version 1.0.3: caption added to Client.Media.Play for improved accessibility by Mike Conley (mike.conley[at]stickmud.com) on 10-MAY-2025.
- Version 2 (proposed, under discussion): direction and pan added to Client.Media.Play; Client.Media.Update and Client.Media.Listener added; "Client.Media 2" advertised in Core.Supports. Proposed by Mike Conley (mike.conley[at]stickmud.com) in October 2026.
Advertise Support for MCMP
Consider advertising your games support of MCMP (and GMCP) to mud lists via the Mud Server Status Protocol, MSSP, by providing a MSSP variable of "MCMP" and value of "1".
Proposed for version 2: a game that sends version 2 messages would give "MCMP" the value "2".
Authors
- Mike Conley (Tamarindo, Co-Administrator at StickMUD and Mudlet contributor) mike.conley[at]stickmud.com
- Eric Oestrich (Developer of ExVenture and Grapevine) eric[at]oestrich.org
Clients
- Known clients implementing this specification:
- Mudlet version 4.4+. See documentation.
- BeipMU version 4.00.298 implements basic load/play/stop commands.
- LociTerm version 2.5.1 and beyond.