PrefectHQ/fastmcp · error

Output schemas must represent object types due to MCP spec l

Error message

Output schemas must represent object types due to MCP spec limitations. Received: {final_output_schema!r}

What it means

The MCP spec only permits tool output schemas of type 'object', so from_function() validates any provided (or inferred) output schema and raises ValueError when the schema root is not an object. This keeps the tool's structured output compliant with the protocol.

Source

Thrown at fastmcp_slim/fastmcp/tools/function_tool.py:341

        # Normalize task to TaskConfig
        task_value = metadata.task
        if task_value is None:
            task_config = TaskConfig(mode="forbidden")
        elif isinstance(task_value, bool):
            task_config = TaskConfig.from_bool(task_value)
        else:
            task_config = task_value
        task_config.validate_function(fn, func_name)

        # Handle output_schema
        if isinstance(metadata.output_schema, NotSetT):
            final_output_schema = parsed_fn.output_schema
        else:
            final_output_schema = metadata.output_schema

        if final_output_schema is not None and isinstance(final_output_schema, dict):
            if not _is_object_schema(final_output_schema):
                raise ValueError(
                    f"Output schemas must represent object types due to MCP spec limitations. "
                    f"Received: {final_output_schema!r}"
                )

        return cls(
            fn=parsed_fn.fn,
            return_type=parsed_fn.return_type,
            name=metadata.name or parsed_fn.name,
            version=str(metadata.version) if metadata.version is not None else None,
            title=metadata.title,
            description=metadata.description
            if metadata.description is not None
            else parsed_fn.description,
            icons=metadata.icons,
            parameters=parsed_fn.input_schema,
            output_schema=final_output_schema,
            annotations=metadata.annotations,
            tags=metadata.tags or set(),

View on GitHub (pinned to 1f02114297)

Solutions

  1. Wrap the return value in an object: return {'items': my_list} and use an object schema
  2. Remove the explicit output_schema and let the library derive a compliant wrapped-object schema
  3. If using a pydantic model, ensure the root model is an object model, not a list/scalar type

Example fix

// before
FunctionTool.from_function(get_ids, output_schema={'type': 'array', 'items': {'type': 'integer'}})
// after
FunctionTool.from_function(get_ids, output_schema={'type': 'object', 'properties': {'ids': {'type': 'array', 'items': {'type': 'integer'}}}, 'required': ['ids']})
Defensive patterns

Strategy: validation

Validate before calling

def ensure_object_schema(schema):
    if schema is None:
        return
    if isinstance(schema, dict) and schema.get('type') != 'object' and 'properties' not in schema:
        raise ValueError(f'Output schema must be object type, got: {schema.get("type")}')

Type guard

def is_object_schema(schema) -> bool:
    return (isinstance(schema, dict)
            and (schema.get('type') == 'object' or 'properties' in schema))

Try / catch

try:
    tool = FunctionTool.from_function(fn, output_schema=schema)
except ValueError as e:
    if 'object types' in str(e):
        tool = FunctionTool.from_function(fn)  # let library derive wrapped schema

Prevention

When it happens

Trigger: Passing output_schema with a non-object root (e.g. {'type': 'array'}, {'type': 'string'}, bool/int schemas) to from_function, or metadata.output_schema being non-object; a wrapped function whose inferred output schema is non-object (via fn schema wrapping it becomes object, so usually explicit user-supplied schemas).

Common situations: Returning lists or scalars from a tool and hand-writing a matching schema; copying JSON Schema fragments from non-MCP projects; wrapping functions returning collections and expecting array schemas.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/f7ea52fe318210b4. Report an issue: GitHub.