from __future__ import annotations import importlib import os import sys from pathlib import Path from typing import Any try: _fastapi_module = importlib.import_module("fastapi") FastAPI = getattr(_fastapi_module, "FastAPI", None) except Exception: FastAPI = None BASE_DIR = Path(__file__).resolve().parent PLUGIN_DIR = BASE_DIR / "flair" / "mcp_output" / "mcp_plugin" if str(PLUGIN_DIR) not in sys.path: sys.path.insert(0, str(PLUGIN_DIR)) if FastAPI is None: raise RuntimeError("fastapi is required to run app.py") app = FastAPI(title="flair MCP info app", version="1.0.0") def _extract_tools(mcp_app: Any) -> list[dict[str, str]]: tools = getattr(mcp_app, "tools", None) output: list[dict[str, str]] = [] if isinstance(tools, dict): iterable = tools.values() elif isinstance(tools, list): iterable = tools else: iterable = [] for item in iterable: name = getattr(item, "name", None) description = getattr(item, "description", None) if not name and isinstance(item, dict): name = str(item.get("name", "")) description = str(item.get("description", "")) if name: output.append({"name": str(name), "description": str(description or "")}) return output @app.get("/") def root() -> dict[str, Any]: return { "service": "flair MCP deployment", "mcp_http_endpoint": "/mcp", "supplementary_app": True, } @app.get("/health") def health() -> dict[str, str]: return {"status": "healthy"} @app.get("/tools") def tools() -> dict[str, Any]: try: mcp_service_module = importlib.import_module("mcp_service") create_app = getattr(mcp_service_module, "create_app") mcp_app = create_app() return {"tools": _extract_tools(mcp_app)} except Exception as exc: return {"tools": [], "error": f"{type(exc).__name__}: {exc}"} if __name__ == "__main__": port = int(os.getenv("PORT", "7860")) try: import uvicorn except Exception as exc: raise RuntimeError("uvicorn is required for local app.py execution") from exc uvicorn.run(app, host="0.0.0.0", port=port)