from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.docs import get_swagger_ui_html from fastapi.staticfiles import StaticFiles import contextlib from app.api.endpoints import ( admin, admin_dashboard, admin_settings, audio, auth, client_downloads, dict_data, external_apps, hot_words, knowledge_base, meetings, prompts, tags, tasks, terminals, users, voiceprint, ) from app.core.config import UPLOAD_DIR from app.core.middleware import TerminalCheckMiddleware from app.mcp import create_mcp_http_app, get_mcp_session_manager from app.services.system_config_service import SystemConfigService def create_app() -> FastAPI: app = FastAPI( title="iMeeting API", description="iMeeting API说明", version="1.1.0", docs_url=None, redoc_url=None, ) app.add_middleware(TerminalCheckMiddleware) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) if UPLOAD_DIR.exists(): app.mount("/uploads", StaticFiles(directory=str(UPLOAD_DIR)), name="uploads") mcp_session_manager = get_mcp_session_manager() mcp_asgi_app = create_mcp_http_app() if mcp_asgi_app is not None: app.mount("/mcp", mcp_asgi_app, name="mcp") app.include_router(auth.router, prefix="/api", tags=["Authentication"]) app.include_router(users.router, prefix="/api", tags=["Users"]) app.include_router(meetings.router, prefix="/api", tags=["Meetings"]) app.include_router(tags.router, prefix="/api", tags=["Tags"]) app.include_router(admin.router, prefix="/api", tags=["Admin"]) app.include_router(admin_dashboard.router, prefix="/api", tags=["AdminDashboard"]) app.include_router(admin_settings.router, prefix="/api", tags=["AdminSettings"]) app.include_router(tasks.router, prefix="/api", tags=["Tasks"]) app.include_router(prompts.router, prefix="/api", tags=["Prompts"]) app.include_router(knowledge_base.router, prefix="/api", tags=["KnowledgeBase"]) app.include_router(client_downloads.router, prefix="/api", tags=["ClientDownloads"]) app.include_router(external_apps.router, prefix="/api", tags=["ExternalApps"]) app.include_router(dict_data.router, prefix="/api", tags=["DictData"]) app.include_router(voiceprint.router, prefix="/api", tags=["Voiceprint"]) app.include_router(audio.router, prefix="/api", tags=["Audio"]) app.include_router(hot_words.router, prefix="/api", tags=["HotWords"]) app.include_router(terminals.router, prefix="/api", tags=["Terminals"]) @app.get("/docs", include_in_schema=False) async def custom_swagger_ui_html(): return get_swagger_ui_html( openapi_url=app.openapi_url, title=app.title + " - Swagger UI", oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, swagger_js_url="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-bundle.js", swagger_css_url="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui.css", ) @app.get("/") def read_root(): return {"message": "Welcome to iMeeting API"} @app.get("/health") def health_check(): return { "status": "healthy", "service": "iMeeting API", "version": "1.1.0", } if mcp_session_manager is not None: @app.on_event("startup") async def startup_mcp_session_manager(): exit_stack = contextlib.AsyncExitStack() await exit_stack.enter_async_context(mcp_session_manager.run()) app.state.mcp_exit_stack = exit_stack @app.on_event("shutdown") async def shutdown_mcp_session_manager(): exit_stack = getattr(app.state, "mcp_exit_stack", None) if exit_stack is not None: await exit_stack.aclose() SystemConfigService.ensure_builtin_parameters() return app