Response handling
FlashMCP processes upstream API responses and formats them into native MCP content blocks that your LLM can understand. Different content types are handled automatically — no configuration needed.
Content types
FlashMCP inspects the Content-Type header of each upstream response and applies the appropriate formatting.
| Content-Type | MCP handling |
|---|---|
application/json |
Parsed and pretty-printed as text content |
text/markdown |
Returned as-is (preferred text format) |
text/plain, text/xml, text/csv |
Returned as text content |
image/* |
Base64-encoded, native MCP image block |
audio/* |
Base64-encoded, native MCP audio block |
204 No Content |
Friendly confirmation message |
JSON responses
JSON is the most common response format from REST APIs. FlashMCP parses the JSON and returns it as a pretty-printed text content block. This makes the response easy for your LLM to read and interpret.
{
"type": "text",
"text": "{\n \"id\": 1,\n \"name\": \"Rex\",\n \"status\": \"available\"\n}"
}
FlashMCP sends the Accept header application/json, text/markdown, text/*;q=0.9, */*;q=0.8 to upstream APIs, preferring JSON and markdown over other formats.
Markdown support
FlashMCP explicitly requests markdown from APIs that support it. Markdown is an ideal format for LLMs — it preserves structure (headings, lists, tables, code blocks) while remaining easy to parse.
Tip: APIs that support Cloudflare's Markdown for Agents feature will return markdown automatically when FlashMCP requests it. This produces cleaner, more structured responses that LLMs can reason about more effectively.
When an API returns text/markdown, the content is passed through directly as a text content block with no additional processing.
Binary content
Images and audio from upstream APIs are automatically encoded into native MCP content blocks. Your LLM receives them as first-class media — not as raw bytes or download links.
Images
Any response with a Content-Type starting with image/ (e.g., image/png, image/jpeg, image/webp) is base64-encoded and returned as an MCP image content block.
{
"type": "image",
"data": "iVBORw0KGgoAAAANSUhEUgAA...",
"mimeType": "image/png"
}
Audio
Responses with audio/* content types (e.g., audio/mpeg, audio/wav) are base64-encoded and returned as MCP audio content blocks.
{
"type": "audio",
"data": "SUQzBAAAAAAAI1RTU0UAAA...",
"mimeType": "audio/mpeg"
}
Empty responses
When an upstream API returns 204 No Content (common for DELETE and some PUT/PATCH operations), FlashMCP generates a friendly confirmation message so your LLM knows the operation succeeded.
{
"type": "text",
"text": "DELETE /pets/42 succeeded (204 No Content)"
}
The message includes the HTTP method and path so the LLM has full context on what operation completed.
Error handling
FlashMCP distinguishes between client errors and server errors, giving your LLM the right signal for each.
Client errors (4xx)
Responses with 4xx status codes (400 Bad Request, 401 Unauthorized, 404 Not Found, 422 Unprocessable Entity, etc.) are returned as regular content without the isError flag. This is intentional — 4xx errors contain useful information that helps the LLM self-correct. For example, a validation error tells the LLM which fields need to be fixed.
{
"content": [{
"type": "text",
"text": "{ \"error\": \"name is required\" }"
}]
// no isError flag — LLM can read and self-correct
}
Server errors (5xx)
Responses with 5xx status codes (500, 502, 503, etc.) are returned with isError: true. These indicate server-side issues that the LLM cannot fix by changing its request, so the error flag tells the LLM not to retry blindly.
{
"content": [{
"type": "text",
"text": "{ \"error\": \"internal server error\" }"
}],
"isError": true
}
Large APIs & pagination
APIs with many endpoints can expose hundreds of tools. To keep things manageable, FlashMCP paginates the tools/list response using cursor-based pagination.
- Each page returns up to 50 tools
- If more tools are available, the response includes a
nextCursorvalue - MCP clients handle pagination automatically — they follow cursors until all tools are loaded
- This prevents tool overload when connecting to large APIs like Stripe (300+ endpoints) or GitHub (600+ endpoints)
{
"tools": [
{ "name": "listCustomers", "..." },
{ "name": "createCustomer", "..." },
// ... 48 more tools
],
"nextCursor": "50"
}
Note: Pagination is handled entirely by the MCP protocol. Your LLM sees all available tools regardless of how many pages they span. No special configuration is required.