PrefectHQ/fastmcp · error · TypeError

server/discover handler returned {type(raw).__name__}; expec

Error message

server/discover handler returned {type(raw).__name__}; expected DiscoverResult or mapping

What it means

The low-level server/discover dispatcher expects the registered handler to return a DiscoverResult instance or a mapping that can be validated into one (unless the handler returned a raw string result outside CORE_RESULT_TYPES). Any other return type raises TypeError naming the actual type returned.

Source

Thrown at fastmcp_slim/fastmcp/server/low_level.py:362

            message = _mw_ctx.message
            params = (
                message.params.model_dump(by_alias=True, mode="json", exclude_none=True)
                if message.params is not None
                else None
            )
            raw = await call_next(replace(ctx, params=params))
            if isinstance(raw, mcp_types.DiscoverResult):
                return raw
            if isinstance(raw, Mapping):
                result = dict(raw)
                result_type = result.get("resultType")
                if (
                    isinstance(result_type, str)
                    and result_type not in mcp_types.CORE_RESULT_TYPES
                ):
                    return result
                return mcp_types.DiscoverResult.model_validate(result)
            raise TypeError(
                "server/discover handler returned "
                f"{type(raw).__name__}; expected DiscoverResult or mapping"
            )

        async with Context(fastmcp=fastmcp, session=ctx.session) as fastmcp_ctx:
            mw_context = MiddlewareContext(
                message=discover_message,
                source="client",
                type="request",
                method="server/discover",
                fastmcp_context=fastmcp_ctx,
            )
            return await fastmcp._run_middleware(
                mw_context,
                cast("FastMCPCallNext[Any, Any]", call_original_handler),
            )

    async def _run_initialize_mw(

View on GitHub (pinned to 1f02114297)

Solutions

  1. Return a DiscoverResult from the handler: return mcp_types.DiscoverResult(servers=[...]).
  2. Return a dict matching the DiscoverResult schema so model_validate can coerce it.
  3. If returning a string result intentionally, ensure it is not one of CORE_RESULT_TYPES or wrap it appropriately.
  4. Inspect the handler for middleware wrappers that may be converting the result to an unsupported type.

Example fix

// before
async def discover_handler(ctx, params):
    return ["server-a", "server-b"]  # TypeError: list returned
// after
async def discover_handler(ctx, params):
    return mcp_types.DiscoverResult.model_validate({"servers": ["server-a", "server-b"]})
Defensive patterns

Strategy: type-guard

Validate before calling

def valid_discover_result(raw) -> bool:
    import mcp.types as mcp_types
    return isinstance(raw, (mcp_types.DiscoverResult, dict))

Type guard

def is_discover_result(raw) -> bool:
    import mcp.types as mcp_types
    return isinstance(raw, mcp_types.DiscoverResult)

Try / catch

try:
    result = await dispatch("server/discover", ctx, params)
except TypeError as e:
    logger.error("Discover handler must return DiscoverResult/mapping: %s", e)
    raise

Prevention

When it happens

Trigger: Registering a custom server/discover handler that returns e.g. a list, a string that is a core result type name, a pydantic model of the wrong type, or None where a result is required.

Common situations: Implementing a custom discovery handler returning plain Python lists of servers; wrapping/middleware that accidentally transforms the result; migrating a handler after the DiscoverResult result-type contract was introduced.

Related errors


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