Standards:MUD Client Media Protocol
MUD Client Media Protocol (MCMP)
A Standard for Loading, Playing, Placing and Stopping Media Files with MUD Clients over GMCP
At a glance
- A game server sends GMCP messages in the
Client.Mediapackage, and the client plays sound, music and video from files it downloads or that the player has installed. - Client.Media.Default and Client.Media.Load get files ready. Client.Media.Play starts them, with optional fades, loops, priorities and captions, and Client.Media.Stop ends them.
- With version 2, a game can say where a sound comes from.
directionorpanon Client.Media.Play places it, Client.Media.Update moves it while it plays, and Client.Media.Listener says which way the player faces. - A game sends the same messages to every client. A client reports its version with
Core.Supports.Set, and a version 1 client ignores the keys and messages it does not know and plays the sound as before. - Please discuss this standard in the MUDstandards channel of the MUD Discord server.
Status of this Memo
This memo describes the Client.Media namespace of the Generic Mud Communication Protocol (GMCP) telnet sub-negotiation protocol (201). It gives the syntax and usage of the JSON messages a game server sends to a text-based game client to load, play, place, move and stop media files. Any client or server can implement them from this memo alone. Mudlet 5.1 and later implement version 2.
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 MUD Client Media Protocol (MCMP) delivers 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. It aims to improve the MUD gaming experience and accessibility through standardized messaging between game servers and game clients. MCMP is inspired by its predecessor Mud Sound Protocol (MSP).
Version 2 lets a game say where a sound comes from, so a player hears a door creak to the north or footsteps coming up from behind, and a blind player can tell where things are.
The design follows three rules:
- Everything new falls back. Version 2 adds only optional keys and messages. A client that does not know one ignores it and plays the sound as before, so a game sends one message to every client.
- Where a sound comes from never depends on hearing it. A client that places a sound also names the direction in the caption it shows.
- Games use the words they already have. A game says
northorbehindinstead of giving coordinates, and each client renders that as well as it can, in 3D, in stereo, or not at all.
Video Demonstration of Client.Media
Overview of the GMCP (201) Sub-negotiation Protocol
GMCP 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 either the client or the server at any time with no warning.
Client.Media is part of the Client.* meta-namespace, and is reserved for game client media operations and future additions to them.
Conventions
The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be read as described in RFC 2119.
| Term | Meaning |
|---|---|
| Media | A sound, music or video file, as its type says.
|
| Placed sound | A sound heard from one point, because it was given a direction or a pan.
|
| Facing | The way the player faces. North, until a game says otherwise with Client.Media.Listener. |
| Angle | Where a sound is from the player's point of view, in degrees clockwise: 0 is ahead, 90 right, 180 behind and 270 left. A compass direction's angle is its bearing minus the facing. |
| 3D client | A client that can place a sound all around the player, including behind, above and below, such as on headphones. |
| Stereo client | A client that can place a sound only between left and right. |
Specification for Client.Media
The Client.Media family of GMCP packages lets games play sound, music and video. Its messages go in one direction, from game server to game client. A player may download media files by hand, and a client may download them automatically.
| Message | Purpose | Version |
|---|---|---|
| Client.Media.Default | Set the default URL to download media files from | 1 |
| Client.Media.Load | Download a media file ahead of time | 1 |
| Client.Media.Play | Play media. Its direction and pan keys say where a sound comes from |
1, and 2 for those keys |
| Client.Media.Update | Move a sound that is playing, or change the volume of media that is playing | 2 |
| Client.Media.Listener | Say which way the player faces | 2 |
| Client.Media.Pause | Pause media until a later Play resumes it | 2 |
| Client.Media.Stop | Stop media | 1 |
Versions and Compatibility
A client SHOULD advertise that it supports Client.Media, with its version number, in a Core.Supports message to the server. A version 1 client sends Client.Media 1.
Core.Supports.Set ["Client.Media 2", ...]
- A client SHOULD advertise version 2 only once it renders
directionandpanand handles Client.Media.Update, Client.Media.Listener and Client.Media.Pause, since servers rely on it. - A server SHOULD look for the package name,
Client.Media, and read the number after it. A server that looks for the exact textClient.Media 1does not recognize a version 2 client. - A version 1 client ignores keys and messages it does not know and plays the sound as before, 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, since a client may drop a whole message whosetypeit does not know, as Mudlet does.
Messages from the Server
Legacy gaming platforms may not support all JSON data types, such as boolean (true and false), so game clients SHOULD also accept booleans and numbers within the Client.Media namespace as strings (surrounded by quotes).
Times are in milliseconds: 1000 milliseconds is 1 second.
Client.Media.Default
Sets the default URL directory to download media files from. A game whose media files download automatically sends this once upon player login.
Client.Media.Default {"url": "https://www.example.com/media/"}
| Key | Required | Value | Purpose |
|---|---|---|---|
url |
Yes | URL | Where the media file can be downloaded from. The last character MUST be a / (slash). |
Note:
Some examples are shown here.
Client.Media.Load
Downloads a media file from an external source ahead of time, for games whose media files download automatically and can be cached by the game client.
Client.Media.Load {
"name": "sword1.mp3",
"url": "https://www.example.com/media/"
}
| Key | Required | Value | Purpose |
|---|---|---|---|
name |
Yes | file name | Name of the media file. It may contain directory information, such as weather/lightning.mp3.
|
url |
Maybe | URL | Where the media file can be downloaded from. The last character MUST be a / (slash). Required only if no URL was set with Client.Media.Default. |
Note:
Some examples are shown here.
Client.Media.Play
Plays media files. A client MAY play only one media file at a time, or several.
Client.Media.Play {
"name": "80_Blacksmith_Shoppe.mp3",
"url": "https://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"
}
| Key | Required | Value | Default | Purpose |
|---|---|---|---|---|
name |
Yes | file name | none | Name of the media file. It may contain directory information, such as weather/lightning.mp3.
|
url |
Maybe | URL | none | Where the media file can be downloaded from. The last character MUST be a / (slash). Required only if the client has to download the file and no URL was set with Client.Media.Default or Client.Media.Load. |
type |
No | "sound", "music" or "video" |
"sound" |
The type of media. |
tag |
No | text | none | Helps categorize media. |
volume |
No | 1 to 100 | 50 | Relative to the volume set on the player's client. |
fadein |
No | milliseconds | none | Volume rises linearly from one to volume over this many milliseconds from the start of the media.
|
fadeout |
No | milliseconds | none | Volume falls linearly from volume to one over this many milliseconds before the end of the media.
|
start |
No | milliseconds | 0 | Begin play at this position. |
finish |
No | milliseconds | the end of the media | End play at this position. |
loops |
No | -1, or 1 or more | 1 | How many times the media plays. -1 loops the sound or music indefinitely. |
priority |
No | 1 to 100 | none | Halts current or future media with a lower priority while this media plays. |
continue |
No | true or false |
true |
true continues playing matching new music files, and false restarts them.
|
key |
No | text | none | Uniquely identifies media files with a key that is bound to their name or url. Halts current media with the same key and a different name or url while this media plays.
|
caption |
No | text | none | Text for captions, such as onomatopoeia or sound cues (thunderclap, whoosh).
|
direction (version 2) |
No | a direction word, or degrees from 0 to 359 | none, so the sound plays as recorded | Where the sound comes from. See Where a Sound Comes From. |
pan (version 2) |
No | -100 to 100 | none, so the sound plays as recorded | Left (-100) to right (100). See Where a Sound Comes From. |
stream (optional) |
No | true or false |
false |
true plays the media as a stream from url and name, such as internet radio, without downloading the file first.
|
close (optional) |
No | true or false |
false |
Video only. true closes the video's window when the video ends or is stopped.
|
- A client MAY support
streamandclose, and ignores them if it does not. A server SHOULD sendstreamonly to a client it knows supports it. A client that ignores the key tries to download the stream as a file, and that download never ends. - A client plays a stream only over HTTP or HTTPS, as with a download, and does not cache it.
Note:
A game can use the caption field to give contextual text to players with hearing impairments or who prefer captioned media. For best practices, see DCMP Captioning Key: Sound Effects and Music.
Note:
Some examples are shown here.
Where a Sound Comes From
A version 1 client ignores direction and pan and plays the sound as it always has.
direction is for games that think in exits and compass points:
- Compass words are the ones MUD exits use:
north,northeast,east,southeast,south,southwest,west,northwest,upanddown, and the short formsn,ne,e,se,s,sw,w,nw,uandd. 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
ahead,behind,leftandright. They are always relative to the player and ignore the facing, soaheadhas an angle of 0,right90,behind180 andleft270. They are for games without compass exits. - Degrees run clockwise from north: 0 is north and 90 is east. A client reads a number outside 0 to 359 as the same direction on the circle, so 360 is north.
- Words are not case sensitive.
- A word the client does not recognize 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, such as footsteps from the shop.
pan is for games that think in speakers rather than compass points, or want a fixed placement. It runs from left (-100) to right (100), and a client treats a value outside that range as the nearest end of it. 0 places the sound at the center, heard from one point. With no pan, it plays as recorded.
Each client renders as much as it can:
- A 3D client places the sound at its angle, including behind, above and below. How high it places
upanddownis its own choice. Directly overhead and underfoot are hard to hear on headphones, so it may use a smaller angle, such as 45° to 60°. - A stereo client turns a direction into pan = 100 × sin(angle). With no facing, east is fully right, west fully left, and north and south are centered.
upanddownname no side, so a stereo client plays those sounds as with no direction. - A client with no panning plays the sound as recorded, as in version 1.
For every client:
- A placed sound is heard from one point. A stereo recording is mixed to one point first. A sound with neither
directionnorpanplays as recorded, stereo image included. - Both keys. When a message has both
pananddirection, a 3D client usesdirectionand a stereo client usespan. That lets a game tune the result for each kind of client. - Captions. A client that shows captions SHOULD add the direction to them, such as a door creaks (north), so that where a sound comes from never depends on hearing it.
- Music and video. These keys are for sounds. A client MAY ignore
directionandpanon"music"and"video". panuses 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 sendingpanis understood by more than one client.
Examples
A door to the north. With no facing, the player hears it ahead, and a client with captions shows a door creaks (north):
Client.Media.Play {
"name": "door-creak.wav",
"key": "north-door",
"volume": 60,
"direction": "north",
"caption": "a door creaks"
}
A drip that stays on the player's left, whichever way they face: {"name": "drip.wav", "pan": -60}
A sound tuned for each kind of client, behind the player on a 3D client and a little to the left on a stereo one: {"name": "wolf.wav", "direction": "behind", "pan": -30}
Client.Media.Update
Version 2. Moves a sound that is already playing, or changes the volume of media that is playing, without restarting it. For 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.
Client.Media.Update {
"key": "dragon",
"direction": "south",
"volume": 80,
"duration": 2000
}
| Key | Required | Value | Default | Purpose |
|---|---|---|---|---|
key |
Maybe | text | none | Selects media with this key. At least one of key, name or tag is required, and media must match all that are given. To move several copies of one sound separately, give each its own key when it is played, such as arrow-1 and arrow-2.
|
name |
Maybe | file name | none | Selects media by name, the same way Client.Media.Stop does. Every playing copy of that file changes. |
tag |
Maybe | text | none | Selects media with this tag. |
type |
No | "sound", "music" or "video" |
any | Narrows the selection to one type. On its own it selects nothing, as it would otherwise change every sound of that type. |
volume |
No | 1 to 100 | unchanged | The new volume. |
direction |
No | as on Client.Media.Play | unchanged | The new direction. |
pan |
No | -100 to 100 | unchanged | The new pan. |
duration |
No | milliseconds | 0 | How long the change takes, as the sound glides from its old values to the new ones. For a traveling sound, give the time it takes to get there. 0 makes the change at once, and a client MAY take up to 20 milliseconds over it, so that the jump does not click. |
- 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.
- A new direction replaces an earlier pan. An update with
directionand nopanclears any pan the sound had, or a stereo client would never move it. An update with onlypanleaves the direction as it was. - Captions. A client does not caption an update. The Play was captioned, and an update only changes how that sound is heard.
Example: A cart that crosses from west to east in four seconds
Client.Media.Play {"name": "cart.wav", "key": "cart", "direction": "west", "caption": "a cart rolls past"}
Client.Media.Update {"key": "cart", "direction": "east", "duration": 4000}
Note:
Some examples are shown here.
Client.Media.Listener
Version 2. Tells the client which way the player faces, so that compass directions are heard relative to it. Most games never send it. Ships, vehicles and games that say "to your left" would. A version 1 client ignores it.
Client.Media.Listener {"facing": "east"}
| Key | Required | Value | Default | Purpose |
|---|---|---|---|---|
facing |
Yes | a compass word other than up or down, or degrees from 0 to 359 |
"north" |
Turns the compass. Facing "east", a sound from the east is ahead and one from the north is to the left.
|
- Relative words are unaffected, as they are always relative to the player.
- A facing the player cannot turn to, such as
upor a relative word, is ignored, and the player keeps the facing they had. - Sounds that are playing turn with the facing, except those with a
pan, which is a fixed placement. - 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.
Note:
Some examples are shown here.
Client.Media.Pause
Version 2. Pauses media that is playing, and a later Play resumes it from the same place. An empty body pauses all media. A version 1 client ignores it, and the media keeps playing.
Client.Media.Pause {
"name": "city.mp3",
"type": "music",
"tag": "environment",
"priority": 60,
"key": "area-background-music"
}
| Key | Required | Value | Purpose |
|---|---|---|---|
name |
No | file name | Pauses media by name matching the value specified. |
type |
No | "sound", "music" or "video" |
Pauses media by type matching the value specified. |
tag |
No | text | Pauses media by tag matching the value specified. |
priority |
No | 1 to 100 | Pauses media with a priority lower than the value. |
key |
No | text | Pauses media by key matching the value specified. |
- Resuming. A Client.Media.Play that matches paused media resumes it where it paused rather than starting it again. A Play with a
keyortagand nonameresumes the paused media it matches. - Stopping. Client.Media.Stop stops paused media too.
Example: Music that pauses while the player reads a scroll
Client.Media.Pause {"key": "area-background-music"}
Client.Media.Play {"key": "area-background-music"}
Note:
Some examples are shown here.
Client.Media.Stop
Stops playing media files. An empty body stops all media.
Client.Media.Stop {
"name": "city.mp3",
"type": "music",
"tag": "environment",
"priority": 60,
"key": "area-background-music",
"fadeaway": true,
"fadeout": 7000
}
| Key | Required | Value | Purpose |
|---|---|---|---|
name |
No | file name | Stops playing media by name matching the value specified. |
type |
No | "sound", "music" or "video" |
Stops playing media by type matching the value specified. |
tag |
No | text | Stops playing media by tag matching the value specified. |
priority |
No | 1 to 100 | Stops playing media with priority less than or equal to the value. |
key |
No | text | Stops playing media by key matching the value specified. |
fadeaway |
No | true or false |
Decreases volume from the current position for a given duration, then stops the media. That duration is the lesser of the media's remaining duration and the fadeout specified in Client.Media.Play. If Client.Media.Play gave no fadeout, then the fadeout key of this message or a default of 5000 milliseconds applies.
|
fadeout |
No | milliseconds | Default duration to decrease volume to the end of the media. Only used if fadeout was not defined in Client.Media.Play.
|
Note:
Some examples are shown here.
Security
A media message comes from the game server, and a client acts on its file names and URLs. Clients MUST treat them as untrusted input:
- Keep files in the media folder. Refuse a name that is an absolute path, or that leads out of the folder through
..or a symbolic link. A client writes what it downloads under these names, so a game could otherwise overwrite the player's files, or read them. - Fetch only over HTTP or HTTPS. Refuse any other scheme, such as
file:, so that a URL cannot turn a download into reading a local file.
Guidance for Servers
Add features in steps:
- Sound and music. Send Client.Media.Default once upon player login, then Client.Media.Play and Client.Media.Stop.
- Captions. Give each sound a
caption, for players with hearing impairments or who prefer captioned media. - Direction. Add
directionto sounds that come from somewhere. You can send it to any client, and need to check for version 2 only if gameplay depends on it. - Movement. Give a traveling sound a
key, and send Client.Media.Update as it moves. - Facing. If the player has a facing, such as on a ship, send Client.Media.Listener when it changes and again after each reconnect.
Also follow these practices from web applications and browsers:
- Avoid autoplay before the player has interacted. Media files should not play immediately upon client connection, especially before the player has had a chance to interact with the game. Some clients, particularly web-based ones, may block or suppress autoplay, and it can disrupt players.
- Use secure media URLs. Whenever possible, serve media files over HTTPS. HTTP links may trigger mixed content warnings or blocked requests in web-based clients and in operating systems with strict security policies.
Advertise Support for MCMP
Consider advertising your game's support of MCMP (and GMCP) to MUD lists via the Mud Server Status Protocol, MSSP, by providing an MSSP variable of "MCMP" and a value of "1". A game that sends version 2 messages gives the value "2".
Guidance for Clients
Implement in levels, and follow the security rules from the start:
- Support Client.Media.Default, Client.Media.Load, Client.Media.Play and Client.Media.Stop, with captions, and advertise
Client.Media 1. - Support
directionandpanon sounds in stereo, and name the direction in captions. - Support Client.Media.Update, Client.Media.Listener and Client.Media.Pause, then advertise
Client.Media 2. - If the platform allows it, place sounds in 3D, perhaps behind a preference for speakers or headphones.
Notes for Web Client Developers
Browser security models limit media playback in ways neither the game server nor the client developer controls:
- Most browsers restrict media autoplay until the user has interacted with the page, so a
Client.Media.Playsent immediately after connection may not play. - Serving media over non-HTTPS URLs may result in blocked requests or mixed content warnings, depending on the browser and hosting setup.
- 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
pananddirectionon music, which is often streamed from elsewhere.
Where possible, client developers may want to inform players or log these situations for debugging.
Quick Reference
Every message, with every key:
Client.Media.Default {"url": "https://www.example.com/media/"}
Client.Media.Load {"name": "sword1.mp3", "url": "https://www.example.com/media/"}
Client.Media.Play {
"name": "door-creak.wav", "url": "https://www.example.com/media/",
"type": "sound", "tag": "environment", "volume": 50,
"fadein": 500, "fadeout": 500, "start": 0, "finish": 3000,
"loops": 1, "priority": 50, "continue": true,
"key": "north-door", "caption": "a door creaks",
"direction": "north", "pan": 0, "stream": false, "close": false
}
Client.Media.Update {
"key": "north-door", "name": "door-creak.wav", "tag": "environment", "type": "sound",
"volume": 80, "direction": "south", "pan": 0, "duration": 2000
}
Client.Media.Listener {"facing": "east"}
Client.Media.Pause {
"name": "door-creak.wav", "type": "sound", "tag": "environment", "priority": 50,
"key": "north-door"
}
Client.Media.Stop {
"name": "door-creak.wav", "type": "sound", "tag": "environment", "priority": 50,
"key": "north-door", "fadeaway": true, "fadeout": 500
}
Left Out on Purpose
These came up in the discussion of version 2, and were left out to keep the protocol small:
distance:volumestays 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
directionto the Play it sends. - Height in degrees:
upanddownare 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.
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: direction and pan added to Client.Media.Play; Client.Media.Update, Client.Media.Listener and Client.Media.Pause added; stream and close listed as optional keys of Client.Media.Play; "Client.Media 2" advertised in Core.Supports. By Mike Conley (mike.conley[at]stickmud.com), with feedback from SlySven, w, Sammer (Luke) and vadi2 in the MUDstandards channel and in review. First implemented in Mudlet 5.1, released on 01-NOV-2026.
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 4.4 and later, and version 2 from Mudlet 5.1. See documentation.
- BeipMU version 4.00.298 implements basic load/play/stop commands.
- LociTerm version 2.5.1 and beyond.
References
- Mud Sound Protocol - the predecessor of MCMP
- RFC 854 - Telnet Protocol Specification
- RFC 2119 - Key words for use in RFCs to Indicate Requirement Levels
- DCMP Captioning Key: Sound Effects and Music - for writing captions
- Mongoose MOO web client - its MCMP extension is prior art for
panand Client.Media.Update - MUD Client Media Protocol in the Mudlet manual - examples for each message