PMFlow/backend/app/api/mcp_api/routes.py

137 lines
4.3 KiB
Python

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)