Output schemas make tool responses predictable. AI clients can know in advance what shape the data will have, enabling structured reasoning without parsing guesswork.
Purpose
Without output schemas, an AI client calling a FlowMCP tool receives an opaque blob of JSON. Output schemas solve this by declaring the expected response shape at the route level:
AI clients can pre-allocate structured reasoning about response fields
Schema validators can verify handler output matches the declaration
Documentation generators can produce accurate response tables automatically
Route-Level Output Definition
Each route can optionally define an output field:
routes : {
getTokenPrice : {
method : 'GET' ,
path : '/simple/price' ,
description : 'Get current token price' ,
parameters : [ /* ... */ ],
output : {
mimeType : 'application/json' ,
schema : {
type : 'object' ,
properties : {
id : { type : 'string' , description : 'Token identifier' },
symbol : { type : 'string' , description : 'Token symbol' },
price : { type : 'number' , description : 'Current price in USD' },
marketCap : { type : 'number' , description : 'Market capitalization' , nullable : true },
volume24h : { type : 'number' , description : 'Trading volume (24h)' }
}
}
}
}
}
The output field lives in the main block and is part of the hashable, JSON-serializable schema surface.
Output Fields
Field Type Required Description mimeTypestringYes Response content type schemaobjectYes Simplified JSON Schema describing the data field
Both fields are required when output is present. If a route does not declare output, omit the entire field.
Supported MIME Types
MIME Type Description Schema type application/jsonJSON response (default) object or arrayimage/pngPNG image, base64-encoded string with format: 'base64'text/plainPlain text response string
Standard Response Envelope
Every FlowMCP tool response is wrapped in a standard envelope:
Success Response
Error Response
{
status : true ,
messages : [],
data : { /* described by output.schema */ }
}
Field Type Description statusbooleantrue on success, false on errormessagesarrayEmpty on success, error descriptions on failure dataobject or nullResponse payload on success, null on error
The output.schema describes only the data field when status: true. Schema authors do not declare the envelope — it is implicit and standardized.
Supported JSON Schema Subset
FlowMCP uses a deliberately constrained subset of JSON Schema:
Supported Keywords
Keyword Description Example typeValue type 'string', 'number', 'boolean', 'object', 'array'propertiesObject properties { name: { type: 'string' } }itemsArray item schema { type: 'object', properties: {...} }descriptionHuman-readable description 'Current price in USD'nullableCan be null trueenumAllowed values ['active', 'inactive']formatSpecial format hint 'base64', 'date-time', 'uri'
Intentionally Excluded Keywords
$ref — no schema references; output schemas are self-contained
oneOf, anyOf, allOf — no union types
required — all declared properties are informational
additionalProperties — APIs may return extra fields
pattern, minimum, maximum — no regex or range validation on output
Response Examples
Object Response
output : {
mimeType : 'application/json' ,
schema : {
type : 'object' ,
properties : {
id : { type : 'string' , description : 'Token identifier' },
price : { type : 'number' , description : 'Current price in USD' },
marketCap : { type : 'number' , description : 'Market cap' , nullable : true }
}
}
}
Array Response
output : {
mimeType : 'application/json' ,
schema : {
type : 'array' ,
items : {
type : 'object' ,
properties : {
name : { type : 'string' , description : 'Protocol name' },
tvl : { type : 'number' , description : 'Total value locked in USD' }
}
}
}
}
Nested Objects
Properties can be objects up to 4 levels deep:
output : {
mimeType : 'application/json' ,
schema : {
type : 'object' ,
properties : {
token : {
type : 'object' ,
description : 'Token metadata' ,
properties : {
name : { type : 'string' , description : 'Token name' },
contract : {
type : 'object' ,
description : 'Contract details' ,
properties : {
address : { type : 'string' , description : 'Contract address' },
verified : { type : 'boolean' , description : 'Verification status' }
}
}
}
}
}
}
}
Image Response
output : {
mimeType : 'image/png' ,
schema : {
type : 'string' ,
format : 'base64' ,
description : 'Chart image as base64-encoded PNG'
}
}
Text Response
output : {
mimeType : 'text/plain' ,
schema : {
type : 'string' ,
description : 'Raw contract source code'
}
}
Nullable Fields
Fields that may be null in a successful response must declare nullable: true:
properties : {
marketCap : { type : 'number' , description : 'Market cap' , nullable : true },
website : { type : 'string' , description : 'Project URL' , nullable : true }
}
This helps AI clients differentiate between “field not available” (nullable) and “field should always be present” (not nullable).
Format Description Example Value base64Base64-encoded binary data 'iVBORw0KGgo...'date-timeISO 8601 date-time '2026-02-16T12:00:00Z'uriValid URI 'https://etherscan.io/address/0x...'
Format is informational — the runtime does not validate format compliance.
Output Schema and Handlers
When a route has a postRequest handler, the output schema describes the final response after handler transformation, not the raw API response.
The output.schema describes the shape after postRequest transforms the data
If postRequest flattens nested responses, the schema describes the flat structure
If no postRequest handler exists, the schema describes the raw API response
Non-Blocking Validation
Output schema validation is non-blocking . A mismatch between the actual handler output and the declared schema produces a validation warning , not an error. The response is still delivered.
This design reflects reality: external APIs may change response shapes without notice. A strict error would break the tool even though the data might still be usable.