From a quick glance at the spec, it seems that everything is an event and it roughly has the following structure:
{
[...]
"room_id": "...",
"content": "<the actual payload>",
[...]
}
The way I see it, the easiest way to make OTR happen is to keep the general JSON structure in the clear so that all servers know the context (in particular the room_id must be understood by the servers to know where the message is to be routed) and have the content be encrypted in a format that only the client(s) understand:
{
[...]
"room_id": "...",
"content": "<encrypted payload>",
[...]
}
This is actually how PGP on SMTP works: the servers know where to route the message, and forward the content without looking at it or trying to understand it. The servers know the very minimum, so their implementation remain easy and understandable, and they critically don't need to be reliable for end-to-end encryption to work.
Being a fan of IM systems I'm interested in Matrix, specifically because it tries to blend in what didn't work with IRC and XMPP, so I may very well look into it a little bit more ...