OpenBB-finance/OpenBB · critical · TypeError

Error: The {name} instance in '{app_path}' is not an instanc

Error message

Error: The {name} instance in '{app_path}' is not an instance of FastAPI

What it means

Final TypeError from the app importer: the resolved attribute (after optional factory call) is not an instance of FastAPI. The MCP server only mounts FastAPI applications, so Flask apps, Starlette apps, routers, or arbitrary objects are rejected at this guard.

Source

Thrown at openbb_platform/extensions/mcp_server/openbb_mcp_server/utils/app_import.py:98

    # Here we use the same approach as uvicorn to handle factory functions.
    # This prevents us from relying on explicit type annotations.
    # See: https://github.com/encode/uvicorn/blob/master/uvicorn/config.py
    try:
        app = app_or_factory()
        if not factory:
            print(  # noqa: T201
                "\n\n[WARNING]   "
                "App factory detected. Using it, but please consider setting the --factory flag explicitly.\n"
            )
    except TypeError:
        if factory:
            raise TypeError(  # pylint: disable=raise-missing-from
                f"Error: The {name} instance in '{app_path}' appears not to be a callable factory function"
            )
        app = app_or_factory

    if not isinstance(app, FastAPI):
        raise TypeError(
            f"Error: The {name} instance in '{app_path}' is not an instance of FastAPI"
        )

    return app


cl_doc = """OpenBB MCP Server

Usage:
    >>> python -m openbb_mcp_server [OPTIONS]

    >>> openbb-mcp --app ./some_app.py --host 0.0.0.0 --port 8005

Description:
    The OpenBB MCP Server is a component of the OpenBB Platform that provides
    a server for the Model-Context-Protocol. REST endpoints are converted into
    tools and made available to connected clients.

View on GitHub (pinned to 3e071fcc2c)

Solutions

  1. Expose an actual FastAPI instance: app = FastAPI() in the target module (or a factory returning one)
  2. For non-FastAPI services, write a thin FastAPI wrapper/proxy instead of passing the original object
  3. If the factory returns a tuple like (app, lifespan), change it to return just the FastAPI instance

Example fix

# before
# main.py
from flask import Flask
app = Flask(__name__)

# after
from fastapi import FastAPI
app = FastAPI()
Defensive patterns

Strategy: type-guard

Validate before calling

from fastapi import FastAPI

app_obj = getattr(module, name)
app_obj = app_obj() if factory else app_obj
if not isinstance(app_obj, FastAPI):
    raise TypeError(
        f"expected FastAPI, got {type(app_obj).__name__}; "
        "wrap non-FastAPI services in a FastAPI app"
    )

Type guard

from fastapi import FastAPI

def is_fastapi_app(module, name: str, factory: bool = False) -> bool:
    obj = getattr(module, name, None)
    if factory and callable(obj):
        try:
            obj = obj()
        except TypeError:
            return False
    return isinstance(obj, FastAPI)

Try / catch

try:
    app = import_app(app_path, name, factory)
except TypeError as e:
    if "not an instance of FastAPI" in str(e):
        raise SystemExit(
            f"{app_path}:{name} is {type(getattr(module, name)).__name__}; "
            "the MCP server can only mount FastAPI apps"
        ) from e
    raise

Prevention

When it happens

Trigger: --app pointing at a module whose 'app' is a flask.Flask, an APIRouter, a Starlette() instance, or a plain dict/class; or a factory that returns something other than FastAPI. The isinstance(app, FastAPI) check runs after both the direct and factory paths.

Common situations: Trying to wrap an existing Flask service, passing a bare router file expecting it to be mounted, a factory that returns a Starlette app or a tuple (app, lifespan), version mismatch where the imported FastAPI class comes from a different installed copy than the check's.

Related errors


AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14). Data as JSON: /api/errors/d5ae668e1f9a1397. Report an issue: GitHub.