Skip to main content
Glama
servers.py10.4 kB
""" API routes for server management. """ from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from typing import Dict, Any, List, Optional from src.database.database import get_db from src.database import crud from src.config.models import ServerCreate, ServerUpdate, ServerAction router = APIRouter( prefix="/servers", tags=["servers"], ) @router.get("/", response_model=List[Dict[str, Any]]) async def get_servers(section_id: Optional[int] = None, db: AsyncSession = Depends(get_db)): """Get all servers, optionally filtered by section.""" servers = await crud.get_servers(db, section_id) return [ { "id": server.id, "name": server.name, "section_id": server.section_id, "description": server.description, "runtime_definition": server.runtime_definition, "settings": server.settings, "status": server.status, "process_id": server.process_id, "created_at": server.created_at, "updated_at": server.updated_at } for server in servers ] @router.get("/{server_id}", response_model=Dict[str, Any]) async def get_server(server_id: int, db: AsyncSession = Depends(get_db)): """Get a server by ID.""" server = await crud.get_server_by_id(db, server_id) if not server: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Server with ID {server_id} not found" ) # Get section information section = await crud.get_section_by_id(db, server.section_id) return { "id": server.id, "name": server.name, "section_id": server.section_id, "section_name": section.name if section else None, "description": server.description, "runtime_definition": server.runtime_definition, "settings": server.settings, "status": server.status, "process_id": server.process_id, "created_at": server.created_at, "updated_at": server.updated_at } @router.post("/", response_model=Dict[str, Any], status_code=status.HTTP_201_CREATED) async def create_server(server_data: ServerCreate, db: AsyncSession = Depends(get_db)): """Create a new server.""" # Check if section exists section = await crud.get_section_by_id(db, server_data.section_id) if not section: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Section with ID {server_data.section_id} not found" ) # Check if server with this name already exists in the section existing_server = await crud.get_server_by_name(db, server_data.section_id, server_data.name) if existing_server: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"Server with name '{server_data.name}' already exists in section '{section.name}'" ) try: server = await crud.create_server(db, server_data.dict()) return { "id": server.id, "name": server.name, "section_id": server.section_id, "section_name": section.name, "description": server.description, "runtime_definition": server.runtime_definition, "settings": server.settings, "status": server.status, "process_id": server.process_id, "created_at": server.created_at, "updated_at": server.updated_at } except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Failed to create server: {str(e)}" ) @router.put("/{server_id}", response_model=Dict[str, Any]) async def update_server( server_id: int, server_data: ServerUpdate, db: AsyncSession = Depends(get_db) ): """Update a server.""" # Check if server exists server = await crud.get_server_by_id(db, server_id) if not server: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Server with ID {server_id} not found" ) # If section_id is being updated, check if section exists if server_data.section_id is not None and server_data.section_id != server.section_id: section = await crud.get_section_by_id(db, server_data.section_id) if not section: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Section with ID {server_data.section_id} not found" ) # If name is being updated, check if it conflicts with existing server in the section section_id = server_data.section_id if server_data.section_id is not None else server.section_id if server_data.name and server_data.name != server.name: existing_server = await crud.get_server_by_name(db, section_id, server_data.name) if existing_server and existing_server.id != server_id: section = await crud.get_section_by_id(db, section_id) raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"Server with name '{server_data.name}' already exists in section '{section.name if section else 'Unknown'}'" ) # Check if server is running - can't update running server if server.status == "Running": raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"Cannot update server '{server.name}' while it is running. Stop the server first." ) try: updated_server = await crud.update_server(db, server_id, server_data.dict(exclude_unset=True)) if not updated_server: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Server with ID {server_id} not found" ) # Get section information section = await crud.get_section_by_id(db, updated_server.section_id) return { "id": updated_server.id, "name": updated_server.name, "section_id": updated_server.section_id, "section_name": section.name if section else None, "description": updated_server.description, "runtime_definition": updated_server.runtime_definition, "settings": updated_server.settings, "status": updated_server.status, "process_id": updated_server.process_id, "created_at": updated_server.created_at, "updated_at": updated_server.updated_at } except HTTPException: raise except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Failed to update server: {str(e)}" ) @router.delete("/{server_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_server(server_id: int, db: AsyncSession = Depends(get_db)): """Delete a server.""" # Check if server exists server = await crud.get_server_by_id(db, server_id) if not server: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Server with ID {server_id} not found" ) # Check if server is running if server.status == "Running": raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"Cannot delete server '{server.name}' while it is running. Stop the server first." ) success = await crud.delete_server(db, server_id) if not success: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to delete server with ID {server_id}" ) @router.post("/{server_id}/{action}", response_model=Dict[str, Any]) async def server_action( server_id: int, action: str, action_data: Optional[ServerAction] = None, db: AsyncSession = Depends(get_db) ): """Perform an action on a server (start, stop, restart).""" # Check if server exists server = await crud.get_server_by_id(db, server_id) if not server: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Server with ID {server_id} not found" ) # Initialize orchestration engine from src.orchestration.orchestration_engine import OrchestrationEngine from src.config.config_manager import ConfigManager from src.runtime.runtime_engine import RuntimeEngine config_manager = ConfigManager() runtime_engine = RuntimeEngine() orchestration_engine = OrchestrationEngine(config_manager, runtime_engine) # Set default values if action_data is not provided force = False timeout = 30 if action_data: force = action_data.force or force timeout = action_data.timeout or timeout try: # Perform the action if action == "start": success, message = await orchestration_engine.start_server(db, server_id) elif action == "stop": success, message = await orchestration_engine.stop_server(db, server_id, force, timeout) elif action == "restart": success, message = await orchestration_engine.restart_server(db, server_id, force, timeout) else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Invalid action: {action}. Must be one of: start, stop, restart" ) if not success: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=message ) # Get updated server status updated_server = await crud.get_server_by_id(db, server_id) return { "id": server_id, "name": server.name, "action": action, "status": updated_server.status if updated_server else "Unknown", "message": message } except HTTPException: raise except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to perform {action} action: {str(e)}" )

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rblake2320/sectional-mcp-panel'

If you have feedback or need assistance with the MCP directory API, please join our Discord server