|
|
from fastapi import APIRouter, HTTPException, Depends, Query |
|
|
from typing import List, Optional, Dict, Any |
|
|
from pydantic import BaseModel, validator, HttpUrl |
|
|
|
|
|
from utils.auth_utils import get_current_user_id_from_jwt |
|
|
from utils.logger import logger |
|
|
from .infrastructure.dependencies import get_mcp_dependencies |
|
|
from .domain.exceptions import MCPException, MCPServerNotFoundError, MCPToolNotFoundError |
|
|
|
|
|
|
|
|
router = APIRouter() |
|
|
|
|
|
def get_mcp_manager(): |
|
|
dependencies = get_mcp_dependencies() |
|
|
return dependencies.mcp_manager |
|
|
|
|
|
|
|
|
class MCPServerResponse(BaseModel): |
|
|
qualified_name: str |
|
|
display_name: str |
|
|
description: str |
|
|
created_at: str |
|
|
use_count: int |
|
|
homepage: str |
|
|
icon_url: Optional[str] = None |
|
|
is_deployed: Optional[bool] = None |
|
|
tools: Optional[List[Dict[str, Any]]] = None |
|
|
security: Optional[Dict[str, Any]] = None |
|
|
|
|
|
|
|
|
class MCPServerListResponse(BaseModel): |
|
|
servers: List[MCPServerResponse] |
|
|
pagination: Dict[str, int] |
|
|
|
|
|
|
|
|
class MCPServerDetailResponse(BaseModel): |
|
|
qualified_name: str |
|
|
display_name: str |
|
|
icon_url: Optional[str] = None |
|
|
deployment_url: Optional[str] = None |
|
|
connections: List[Dict[str, Any]] |
|
|
security: Optional[Dict[str, Any]] = None |
|
|
tools: Optional[List[Dict[str, Any]]] = None |
|
|
|
|
|
|
|
|
class PopularServersResponse(BaseModel): |
|
|
success: bool |
|
|
servers: List[Dict[str, Any]] |
|
|
categorized: Dict[str, List[Dict[str, Any]]] |
|
|
total: int |
|
|
category_count: int |
|
|
pagination: Dict[str, int] |
|
|
|
|
|
|
|
|
class CustomMCPConnectionRequest(BaseModel): |
|
|
url: str |
|
|
config: Optional[Dict[str, Any]] = {} |
|
|
|
|
|
|
|
|
class CustomMCPConnectionResponse(BaseModel): |
|
|
success: bool |
|
|
qualified_name: str |
|
|
display_name: str |
|
|
tools: List[Dict[str, Any]] |
|
|
config: Dict[str, Any] |
|
|
url: str |
|
|
message: str |
|
|
|
|
|
|
|
|
class CustomMCPDiscoverRequest(BaseModel): |
|
|
type: str |
|
|
config: Dict[str, Any] |
|
|
|
|
|
|
|
|
|
|
|
@router.get("/mcp/servers/{qualified_name:path}", response_model=MCPServerDetailResponse) |
|
|
async def get_mcp_server_details( |
|
|
qualified_name: str, |
|
|
user_id: str = Depends(get_current_user_id_from_jwt) |
|
|
): |
|
|
try: |
|
|
manager = get_mcp_manager() |
|
|
server_detail = await manager.get_server_details(qualified_name) |
|
|
|
|
|
return MCPServerDetailResponse( |
|
|
qualified_name=server_detail.qualified_name, |
|
|
display_name=server_detail.display_name, |
|
|
icon_url=server_detail.icon_url, |
|
|
deployment_url=server_detail.deployment_url, |
|
|
connections=server_detail.connections, |
|
|
security=server_detail.security, |
|
|
tools=server_detail.tools |
|
|
) |
|
|
|
|
|
except MCPServerNotFoundError: |
|
|
raise HTTPException(status_code=404, detail="MCP server not found") |
|
|
except MCPException as e: |
|
|
logger.error(f"Error getting MCP server details: {str(e)}") |
|
|
raise HTTPException(status_code=500, detail=str(e)) |
|
|
|
|
|
@router.post("/mcp/discover-custom-tools") |
|
|
async def discover_custom_mcp_tools(request: CustomMCPDiscoverRequest): |
|
|
try: |
|
|
manager = get_mcp_manager() |
|
|
result = await manager.discover_custom_tools(request.type, request.config) |
|
|
|
|
|
return CustomMCPConnectionResponse( |
|
|
success=result.success, |
|
|
qualified_name=result.qualified_name, |
|
|
display_name=result.display_name, |
|
|
tools=result.tools, |
|
|
config=result.config, |
|
|
url=result.url, |
|
|
message=result.message |
|
|
) |
|
|
|
|
|
except MCPException as e: |
|
|
logger.error(f"Error discovering custom MCP tools: {str(e)}") |
|
|
raise HTTPException(status_code=500, detail=str(e)) |