from __future__ import annotations from typing import Any from fastapi import APIRouter, Depends from fastapi.responses import JSONResponse from pydantic import BaseModel, Field from sqlalchemy.ext.asyncio import AsyncSession from ...core.database import get_db from ...core.response import error_response, success_response from ...dependencies import require_manager_user from ...models import User from ...services.mcp_config import McpConfigService router = APIRouter(prefix="/mcp", tags=["mcp_config"]) class McpServerCreateRequest(BaseModel): name: str display_name: str | None = None template_id: str params: dict[str, Any] = Field(default_factory=dict) class McpServerUpdateRequest(BaseModel): name: str | None = None display_name: str | None = None template_id: str | None = None params: dict[str, Any] | None = None def _service(db: AsyncSession, current_user: User) -> McpConfigService: return McpConfigService(db, tenant_id=int(current_user.tenant_id)) @router.get("/admin/catalog") async def get_mcp_catalog( db: AsyncSession = Depends(get_db), current_user: User = Depends(require_manager_user), ): return success_response(await _service(db, current_user).get_catalog()) @router.get("/admin/servers") async def list_mcp_servers( db: AsyncSession = Depends(get_db), current_user: User = Depends(require_manager_user), ): items = await _service(db, current_user).list_servers() return success_response({"items": items}) @router.post("/admin/servers") async def create_mcp_server( body: McpServerCreateRequest, db: AsyncSession = Depends(get_db), current_user: User = Depends(require_manager_user), ): service = _service(db, current_user) try: item = await service.create_server( name=body.name, display_name=body.display_name, template_id=body.template_id, params=body.params, ) except ValueError as exc: await db.rollback() return JSONResponse(status_code=400, content=error_response(400, str(exc))) await db.commit() return success_response(item) @router.put("/admin/servers/{server_id}") async def update_mcp_server( server_id: str, body: McpServerUpdateRequest, db: AsyncSession = Depends(get_db), current_user: User = Depends(require_manager_user), ): service = _service(db, current_user) try: item = await service.update_server( server_id=server_id, name=body.name, display_name=body.display_name, template_id=body.template_id, params=body.params, ) except ValueError as exc: await db.rollback() return JSONResponse(status_code=400, content=error_response(400, str(exc))) except LookupError as exc: await db.rollback() return JSONResponse(status_code=404, content=error_response(404, str(exc))) await db.commit() return success_response(item) @router.post("/admin/servers/{server_id}/validate") async def validate_mcp_server( server_id: str, db: AsyncSession = Depends(get_db), current_user: User = Depends(require_manager_user), ): service = _service(db, current_user) try: payload = await service.validate_server(server_id=server_id) except ValueError as exc: await db.rollback() return JSONResponse(status_code=400, content=error_response(400, str(exc))) except LookupError as exc: await db.rollback() return JSONResponse(status_code=404, content=error_response(404, str(exc))) await db.commit() return success_response(payload) @router.post("/admin/servers/{server_id}/confirm-client-apply") async def confirm_mcp_server_client_apply( server_id: str, db: AsyncSession = Depends(get_db), current_user: User = Depends(require_manager_user), ): service = _service(db, current_user) try: payload = await service.confirm_client_apply(server_id=server_id) except ValueError as exc: await db.rollback() return JSONResponse(status_code=400, content=error_response(400, str(exc))) except LookupError as exc: await db.rollback() return JSONResponse(status_code=404, content=error_response(404, str(exc))) await db.commit() return success_response(payload)