I can vouch for this wholeheartedly! However, be aware that these are all ad-hoc in some fascinating yet depressing ways. I can't help but mention a few names and fun facts...

> 16-bit color encoding

I think the xterm-256 escape codes came from somewhere other than MUDs, but it is forever frustrating to me that whoever designed them used the parameter separator `;` instead of the subparameter separator `:`. For SGR (`\e[m`-type escapes), each parameter is an individual change to the graphic state, so you can combine multiple settings into a single SGR. (For instance, `\e[1;32m` means "bold" followed by "green foreground".) But the 256-color extensions use a pattern "\e[38;5;<n>m", which makes itself into a fresh edge case you have to handle specially instead of treating "38", "5", and the chosen <n> as individual commands. `:` is perfectly well defined as binding more tightly than `;`, so "38:5:<n>" would have worked perfectly well as a definition for the otherwise-undefined "38" code, but no...

> text compression

The MCCP (Mud Client Compression Protocol) is very cool, but its first version called to signal the start of compression with the byte sequence `IAC SB MCCP SE`. The intent was to send an empty MCCP subnegotiation frame and immediately return to the main Telnet channel, but they left off an `IAC` to preceed the `SE`, meaning that this just starts a subnegotion frame, sends `SE` as the first byte, and then forgets to close the frame. Ever. So if you want to support MCCPv1, you have to add a little hack to detect this situation and pretend the frame was actually closed as intended. (Please don't support MCCPv1.)

> hidden sideband metadata communication usable by clients

Yes! One of my favorite topics. Iron Realms-published MUDs introduced "ATCP", another subnegotiation-based protocol that would provide additional information about your character, which directions you can move, your inventory, etc., so that your client could provide graphical representations of this information in the UI. They replaced it with "GMCP" later on -- the "standardization" process behind that was memorable -- which used JSON as the payload format.

Fun fact about ATCP: It was originally designed with a lightweight handshake mechanism so that only Iron Realms clients ("Nexus") could utilize this information. Before my time, someone seems to have reverse engineered this algorithm, so it pretty quickly spread to custom plugins for third-party clients. They never seemed openly upset about this development, and GMCP dropped this mechanism.

And none of this is even getting into MXP, which embedded XML-inspired tags directly into the main data channel instead of using a subnegotiation. The presence of tags is controlled by using a non-standard ANSI-style escape sequence. I never ended up implementing MXP, because ATCP and GMCP were so much simpler to work with, but it's still a very cool piece of tech.

> every single feature has to be totally backwards-compatible with a plain text terminal.

Telnet is actually a shockingly cool little protocol. Sure, there are some anachronisms, like the "Network Virtual Terminal" (NVT) defining a variety of special text editing commands to provide a common representation for the many terminals sold by many vendors and their incompatible command representations. But Telnet at its core is a data multiplexer with 1 primary data channel and 256 negotiable framed channels ("options"). The mechanism for negotiating the use of a channel is symmetric, meaning that the client and server are on equal footing -- both have to agree, and either one can advertise its willingness to use a channel. It's a really cool protocol to study -- and small enough that you really can understand the whole thing!

Source for all this: I was a MUD enthusiast for several years as a teenager, and wrote my own Telnet stack, ANSI escape parser (referencing the ECMA spec!), and started on my own web-based MUD client. I did a heck of a lot of digging back then on these topics. It's still one of my favorite esoteric technology stacks to play around with.