THE PROBLEM
The MCP server now exposes get-message-recording, wrapping
GET /conversations/messages/{messageId}/locations/{locationId}/recording.
It returns HTTP 200 and real audio. But the audio arrives unusable.
The operation registry declares this endpoint as:
responseContentTypes: ["application/json"]
That is wrong. The endpoint returns audio/x-wav. Because the executor believes the
response is text, it decodes the body as UTF-8 before putting it in the data field.
Every byte that is not valid UTF-8 becomes U+FFFD, the replacement character.
MEASURED ON A REAL 26 SECOND CALL
data is a str of 394220 chars
U+FFFD count: 205969 (52.2% of payload)
non-ASCII bytes that survived: 17
52.2 percent of the audio is replaced by one repeated codepoint. Only 17 high bytes
survived, the ones that happened to form valid UTF-8 sequences by chance.
This is a lossy decode, not base64, so no client-side decoding recovers it. Many
distinct original bytes all collapse to the same U+FFFD.
The damage reaches the header. A WAV begins with "RIFF" plus a 4 byte little-endian
size field:
0x52 0x49 0x46 0x46 R I F F
0xFFFD 0x06 0x06 0x00 <- first size byte already replaced
So it is not a corrupt-but-salvageable file. The length field itself is unreadable.
WHY THIS MATTERS
We run a managed follow-up audit service across agency sub-accounts. HighLevel's own
transcription covers most calls, and get-message-transcription over MCP works
perfectly. We verified it is byte-identical to the REST response: rendered through our
own pipeline, both produce the same 1404 characters, same speaker indices, same
sentence splits. That tool is excellent.
The gap is the remainder. Roughly 8 percent of calls in our pilot account have no
HighLevel transcript, and those need the recording so we can transcribe locally.
That one path forces us to keep a separate Private Integration Token and a parallel
REST client purely to fetch audio the MCP already reaches but mangles.
THE FIX (any one of these works)
Option A: Correct the content type in the operation registry so the executor stops
decoding binary as text, and return the audio base64 encoded.
Option B: Return a short-lived signed URL instead of the bytes. Better for MCP
generally, since audio files do not belong in a tool result. This matches what was
requested for Voice AI recordings in a separate idea on the Voice AI board.
Option C: Expose the Twilio Recording SID on TYPE_CALL messages. The Call SID is
already present as altId. Only the Recording SID is missing, and clients could then
construct the URL themselves.
BROADER POINT
This is not really a feature request. It is a spec bug with a one line fix, and it
will silently affect any other binary-returning operation in the registry that carries
the same wrong content type. Worth auditing the generated registry for others.
Related and now largely shipped:
That request asked for three tools. All three now exist. Transcription works. Recording
is the one that is broken.