This is an old thread, but since I ran into the exact same issue, and this thread was the only source I could find on the web that even raises the question of MCDI frame size, I thought I should add the answer that I found out eventually.
What's the issue?
Like the OP, I encountered various files with an MCDI frame in their ID3v2.3 tag. In many (all?) these cases, the size of that frame appeared to be off-by-one and the following tag (typically TLEN) started one byte later than expected. This threw off my own decoder.
It didn't help that the content of that frame was binary data (the dump of a CD's TOC), whose format I had trouble finding accurate documentation for.
What's the reason?
In short, the unsynchronisation scheme.
It turns out the unsynchronisation bit was set in the offending ID3v2.3 header. That causes all sequences of $FF Fx bytes in the body of the tag to be replaced with $FF 00 Fx.
Most frames do not contain data where such byte sequences would even show up. But the binary data contained in the MCDI frame seems to regularly end in $FF FF ā which becomes $FF 00 FF after unsynchronisation is applied.
Now, unfortunately, this feature is documented somewhat poorly. The ID3v2.3 spec clearly says that the size field in the tag header is computed after unsynchronisation is applied. However, what it does not say explicitly is that the size of frames apparently is computed before unsynchronisation ā that's because unsynchronisation is applied to the tag as a whole.
Moreover, this was changed in ID3v2.4, where unsynchronisation is now applied per frame, such that frame sizes are finally 'correct'.
What's the implication
More fun and special casing for decoders... For ID3v2.3, you cannot decode or skip frames without looking at every byte in them.
Worse, in 2.3, the frame size itself actually is subject to the unsynchronisation scheme. That is, if a size value happens to contain a $FF byte, you better check whether it's followed by $00 and skip that.