mudsplatjs
v1.0.0
Published
Telnet+GMCP+MCCP to WebSocket proxy for MUD clients
Maintainers
Readme
MUDSplat.js
Telnet+GMCP+MCCP+MXP to WebSocket proxy for MUD clients. Play any MUD from a browser, build bots, or pipe structured game data into your own frontend.
┌─────────────┐ WebSocket ┌─────────────┐ Telnet ┌──────────┐
│ Browser / │◄──────────────────►│ MudProxy │◄────────────────►│ MUD │
│ xterm.js │ JSON messages │ (Node.js) │ GMCP+MCCP+MXP │ Server │
└─────────────┘ └─────────────┘ └──────────┘Install
npm install mudsplatjs
# or
pnpm add mudsplatjsWhat is this?
MUDSplat.js handles the gnarly parts of connecting to a MUD — telnet negotiation, GMCP structured data, MCCP2 compression, and MXP rich text — so you can focus on building your client or bot. It gives you two ways in:
- Web client: Run the proxy server, connect from your browser via WebSocket. ANSI escape codes are passed through raw so xterm.js renders them natively. GMCP and MXP arrive as parsed JSON.
- Bot / script: Use
MudConnectiondirectly from Node.js. No proxy needed.
Building a Web Client
You need two pieces: a proxy server (Node.js) and a browser client.
1. Create your proxy server
// server.js
const { MudProxy } = require('mudsplatjs');
const proxy = new MudProxy({ port: 8080 });
proxy.on('listening', ({ port }) => {
console.log(`MUDSplat proxy on port ${port}`);
});
proxy.start();node server.js2. Connect from your browser
The package includes a browser client at mudsplatjs/client. For a typical xterm.js setup:
<script src="node_modules/mudsplatjs/src/client.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm/lib/xterm.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm/css/xterm.min.css">
<div id="terminal"></div>
<script>
const terminal = new Terminal();
terminal.open(document.getElementById('terminal'));
const mud = new MudSplatClient('ws://localhost:8080');
// ANSI output goes straight to xterm.js — colors, bold, etc. just work
mud.on('output', (text) => terminal.write(text));
// Structured game data via GMCP
mud.on('gmcp', (name, data) => {
if (name === 'Char.Vitals') updateHealthBar(data);
if (name === 'Room.Info') updateMap(data);
});
// Clickable MXP elements (exits, items, etc.)
mud.on('mxp', (elements) => {
for (const el of elements) {
if (el.type === 'send') renderClickable(el.text, el.command);
}
});
// Connect to a MUD
await mud.connect('aardmud.org', 4000);
// Send commands from user input
terminal.onData((text) => mud.send(text));
</script>The proxy talks JSON over WebSocket. Your client sends commands like { "type": "input", "text": "look" } and receives output, GMCP, MXP, and status events. See the full WebSocket protocol below.
Building a Bot or Script
Skip the proxy — connect to a MUD directly from Node.js:
const { MudConnection } = require('mudsplatjs');
const mud = new MudConnection({
host: 'aardmud.org',
port: 4000,
gmcpPackages: ['Core 1', 'Char 1', 'Room 1'],
});
// Raw text output (including ANSI codes)
mud.on('data', (text) => process.stdout.write(text));
// Structured data — no need to parse text
mud.on('gmcp', ({ name, data }) => {
if (name === 'Char.Vitals') {
console.log(`HP: ${data.hp}/${data.maxhp}`);
}
});
mud.on('close', () => {
console.log('Disconnected');
process.exit(0);
});
await mud.connect();
mud.send('look');If you need to strip ANSI for logging or plain-text processing:
const { stripAnsi } = require('mudsplatjs');
mud.on('data', (text) => {
fs.appendFileSync('mud.log', stripAnsi(text));
});Features
- WebSocket proxy — bridge any telnet MUD to WebSocket clients with a JSON protocol
- GMCP — structured game data: vitals, room info, inventory, channels, skills
- MCCP2 — transparent zlib decompression of compressed MUD streams
- MXP — clickable commands, links, and rich text elements parsed into structured data
- ANSI passthrough — raw escape codes forwarded untouched for xterm.js / terminal rendering
- Direct connections —
MudConnectionclass for server-side bots and scripts - Browser client — lightweight
MudSplatClientfor frontend apps - Host whitelisting — restrict which MUDs the proxy can connect to
- TypeScript definitions included
WebSocket Protocol
All messages are JSON with a type field.
Client to Proxy
| Type | Fields | Description |
|------|--------|-------------|
| connect | host, port, gmcpPackages? | Open a MUD connection |
| input | text | Send a command (newline added automatically) |
| gmcp | name, data? | Send a GMCP message |
| disconnect | — | Close the MUD connection |
Proxy to Client
| Type | Fields | Description |
|------|--------|-------------|
| output | text | Raw text from the MUD (with ANSI escape codes) |
| gmcp | name, data | Parsed GMCP message |
| mxp | elements, mode | Parsed MXP elements (send, link, formatting) |
| prompt | text | Prompt detected (via Telnet GA) |
| connected | host, port | MUD connection established |
| disconnected | — | MUD connection closed |
| mccp | active | Compression state changed |
| error | message | Error |
Proxy Options
new MudProxy({
port: 8080, // WebSocket port
host: '0.0.0.0', // Bind address
allowedHosts: [], // MUD host whitelist (empty = allow all)
maxConnections: 100, // Max simultaneous connections
gmcp: true, // Enable GMCP
mccp: true, // Enable MCCP2
mxp: true, // Enable MXP
});Documentation
Full API reference, protocol docs, and GMCP/MCCP/MXP guides: lazerthings.github.io/mudsplatjs
License
Apache-2.0
