Skip to main content
Glama
ARCHITECTURE.md18.9 kB
# Architecture Documentation This document provides a comprehensive overview of the Aerospace MCP system design, architecture decisions, and technical considerations. ## Table of Contents - [System Overview](#system-overview) - [Component Architecture](#component-architecture) - [Data Flow](#data-flow) - [Technology Stack](#technology-stack) - [Design Decisions](#design-decisions) - [Performance Considerations](#performance-considerations) - [Security Considerations](#security-considerations) - [Scalability & Future Enhancements](#scalability--future-enhancements) ## System Overview The Aerospace MCP (Model Context Protocol) system is a flight planning service that provides: - **Airport Resolution**: Intelligent mapping from city names to airport codes - **Route Calculation**: Great-circle distance computation with geodesic precision - **Performance Estimation**: Aircraft-specific fuel and time calculations using OpenAP - **API Services**: RESTful endpoints and MCP protocol support ### High-Level Architecture ```mermaid graph TB Client[Client Applications] MCP[MCP Protocol Layer] API[FastAPI Application] Core[Core Services] Data[Data Sources] Client --> MCP Client --> API MCP --> API API --> Core Core --> Data subgraph "Core Services" Airport[Airport Resolution] Route[Route Calculation] Perf[Performance Estimation] end subgraph "Data Sources" AirportDB[Airport Database] OpenAP[OpenAP Models] Geodesic[Geographiclib] end Airport --> AirportDB Route --> Geodesic Perf --> OpenAP ``` ## Component Architecture ### 1. Application Layer (main.py) The main application serves as the orchestration layer, handling: - HTTP request/response processing - Input validation via Pydantic models - Error handling and status code management - Dependency coordination ### 2. Core Service Components #### Airport Resolution Service ```mermaid graph LR Input[City Name + Country] --> Search[City Search Logic] Search --> Filter[Country Filter] Filter --> Rank[Airport Ranking] Rank --> Output[Selected Airport] subgraph "Data Access" Search --> AirportDB[airportsdata.load] Filter --> AirportDB end subgraph "Business Logic" Rank --> IntlPref[Prefer International] Rank --> NameMatch[Name Matching] end ``` **Key Functions**: - `_find_city_airports()`: Fuzzy city name matching - `_resolve_endpoint()`: Airport selection with fallback logic - `_airport_from_iata()`: Direct IATA code lookup **Design Patterns**: - **Strategy Pattern**: Supports city search vs. direct IATA lookup - **Filter Pattern**: Progressive filtering by city, country, airport type - **Fallback Pattern**: Graceful degradation when specific airports unavailable #### Route Calculation Service ```mermaid graph LR Origin[Origin Airport] --> GC[Great Circle Calculation] Dest[Destination Airport] --> GC GC --> Sample[Route Sampling] Sample --> Polyline[Polyline Generation] subgraph "Geodesic Engine" GC --> Geodesic[geographiclib.Geodesic] Sample --> Line[Geodesic.Line] Sample --> Position[Line.Position] end ``` **Key Functions**: - `great_circle_points()`: Generates sampled route coordinates - Configurable sampling resolution via `route_step_km` - WGS84 geodesic calculations for accuracy **Mathematical Foundation**: - Uses Vincenty's formulae for geodesic calculations - Accounts for Earth's ellipsoidal shape (WGS84) - Samples route at configurable intervals for visualization #### Performance Estimation Service ```mermaid graph TB Aircraft[Aircraft Type] --> Props[Aircraft Properties] Route[Route Distance] --> Segments[Flight Segments] Mass[Aircraft Mass] --> FuelFlow[Fuel Flow Models] subgraph "OpenAP Integration" Props --> FlightGen[FlightGenerator] FlightGen --> Climb[Climb Profile] FlightGen --> Cruise[Cruise Profile] FlightGen --> Descent[Descent Profile] end subgraph "Calculations" Segments --> Time[Time Estimation] FuelFlow --> Fuel[Fuel Estimation] Time --> Block[Block Time] Fuel --> Block[Block Fuel] end ``` **Key Functions**: - `estimates_openap()`: OpenAP-based performance calculations - Aircraft property resolution with MTOW defaults - Three-phase flight modeling (climb/cruise/descent) ### 3. Data Models & Validation ```mermaid classDiagram class AirportOut { +string iata +string icao +string name +string city +string country +float lat +float lon +string tz } class PlanRequest { +string depart_city +string arrive_city +string depart_country +string arrive_country +string prefer_depart_iata +string prefer_arrive_iata +string ac_type +int cruise_alt_ft +float mass_kg +float route_step_km +string backend } class PlanResponse { +string engine +AirportOut depart +AirportOut arrive +float distance_km +float distance_nm +List polyline +dict estimates } class SegmentEst { +float time_min +float distance_km +float avg_gs_kts +float fuel_kg } PlanResponse --> AirportOut : contains PlanResponse --> SegmentEst : estimates ``` ## Data Flow ### Flight Planning Request Flow ```mermaid sequenceDiagram participant Client participant FastAPI participant AirportResolver participant RouteCalculator participant PerformanceEstimator participant OpenAP Client->>FastAPI: POST /plan FastAPI->>FastAPI: Validate PlanRequest FastAPI->>AirportResolver: Resolve departure airport AirportResolver->>AirportResolver: Search city/IATA AirportResolver-->>FastAPI: Departure airport FastAPI->>AirportResolver: Resolve arrival airport AirportResolver->>AirportResolver: Search city/IATA AirportResolver-->>FastAPI: Arrival airport FastAPI->>RouteCalculator: Calculate great circle route RouteCalculator->>RouteCalculator: Generate polyline RouteCalculator-->>FastAPI: Route & distance FastAPI->>PerformanceEstimator: Estimate performance PerformanceEstimator->>OpenAP: Get aircraft properties OpenAP-->>PerformanceEstimator: Aircraft data PerformanceEstimator->>OpenAP: Generate flight profiles OpenAP-->>PerformanceEstimator: Climb/cruise/descent PerformanceEstimator->>PerformanceEstimator: Calculate fuel flow PerformanceEstimator-->>FastAPI: Performance estimates FastAPI->>FastAPI: Assemble PlanResponse FastAPI-->>Client: Complete flight plan ``` ### Error Handling Flow ```mermaid graph TD Request[Incoming Request] --> Validate[Input Validation] Validate -->|Invalid| ValidationError[422 Validation Error] Validate -->|Valid| Process[Process Request] Process --> Airport[Airport Resolution] Airport -->|Not Found| NotFoundError[404 Airport Not Found] Airport -->|Found| Route[Route Calculation] Route --> Performance[Performance Estimation] Performance -->|OpenAP Missing| NotImplementedError[501 Backend Unavailable] Performance -->|Aircraft Invalid| BadRequestError[400 Invalid Aircraft] Performance -->|Success| Response[200 Success Response] ValidationError --> ErrorResponse[Error Response] NotFoundError --> ErrorResponse NotImplementedError --> ErrorResponse BadRequestError --> ErrorResponse ``` ## Technology Stack ### Core Technologies | Component | Technology | Version | Purpose | |-----------|------------|---------|---------| | **Web Framework** | FastAPI | Latest | REST API, async support, auto-docs | | **Validation** | Pydantic | V2 | Data validation, serialization | | **Airport Data** | airportsdata | Latest | IATA/ICAO airport database | | **Geodesics** | geographiclib | Latest | Great-circle calculations | | **Performance** | OpenAP | Latest | Aircraft performance modeling | | **ASGI Server** | Uvicorn | Latest | Production ASGI server | ### Development & Testing | Component | Technology | Purpose | |-----------|------------|---------| | **Package Manager** | UV / pip | Dependency management | | **Testing** | pytest | Unit/integration testing | | **Type Checking** | mypy | Static type analysis | | **Formatting** | black, isort | Code formatting | | **Documentation** | FastAPI + OpenAPI | Auto-generated API docs | ### Data Sources ```mermaid graph LR subgraph "Airport Data" AirportData[airportsdata Package] IATA[IATA Database] OpenFlights[OpenFlights Data] end subgraph "Aircraft Performance" OpenAP[OpenAP Database] BADA[BADA Models] Manufacturers[OEM Data] end subgraph "Geographic" WGS84[WGS84 Geodesic] GeographicLib[GeographicLib] end AirportData --> IATA AirportData --> OpenFlights OpenAP --> BADA OpenAP --> Manufacturers GeographicLib --> WGS84 ``` ## Design Decisions ### 1. Monolithic vs. Microservices **Decision**: Monolithic architecture in single `main.py` **Rationale**: - **Simplicity**: Single deployment unit, minimal operational complexity - **Performance**: No inter-service communication overhead - **Development Speed**: Rapid prototyping and iteration - **Data Locality**: All operations on shared in-memory data **Trade-offs**: - ✅ Faster development, easier debugging, atomic deployments - ❌ Harder to scale individual components, technology lock-in ### 2. In-Memory vs. Database Storage **Decision**: In-memory airport data loading at startup **Rationale**: - **Performance**: Sub-millisecond airport lookups - **Simplicity**: No database configuration or management - **Data Size**: ~28k airports fit comfortably in memory (~50MB) - **Update Frequency**: Airport data changes infrequently **Implementation**: ```python _AIRPORTS_IATA = airportsdata.load("IATA") # Loaded once at startup ``` **Trade-offs**: - ✅ Extremely fast lookups, no external dependencies - ❌ Higher memory usage, startup time, no real-time updates ### 3. Synchronous vs. Asynchronous Processing **Decision**: Synchronous processing with FastAPI async framework **Rationale**: - **CPU-bound Operations**: Flight calculations are computational, not I/O bound - **Third-party Libraries**: OpenAP and geographiclib are synchronous - **Complexity**: Async adds complexity without clear benefit for current use case **Future Consideration**: Could add async for: - External API calls (weather, NOTAMs) - Concurrent flight planning requests - Database operations ### 4. Backend Abstraction Layer **Decision**: Pluggable backend system with single OpenAP implementation **Architecture**: ```python class PlanRequest(BaseModel): backend: Literal["openap"] = "openap" # Extensible enum def plan(req: PlanRequest): if req.backend == "openap": return estimates_openap(...) # Future: elif req.backend == "eurocontrol": # return estimates_eurocontrol(...) ``` **Rationale**: - **Extensibility**: Easy to add new performance estimation engines - **A/B Testing**: Compare different estimation methods - **Fallback**: Graceful degradation if primary backend unavailable ### 5. Error Handling Strategy **Decision**: HTTPException-based error handling with detailed messages **Pattern**: ```python def _resolve_endpoint(city, country, prefer_iata, role): if prefer_iata: ap = _airport_from_iata(prefer_iata) if not ap: raise HTTPException( status_code=400, detail=f"{role}: IATA '{prefer_iata}' not found." ) # ... more validation ``` **Benefits**: - Clear error messages for debugging - Consistent error format across endpoints - Proper HTTP status codes for different error types ## Performance Considerations ### Memory Usage ```mermaid pie title Memory Usage Distribution "Airport Database" : 45 "OpenAP Models" : 25 "Application Code" : 15 "FastAPI Framework" : 10 "Python Runtime" : 5 ``` **Airport Database**: ~50MB for 28k airports with geographic data **OpenAP Models**: Loaded lazily per aircraft type, ~20-30MB per aircraft **Route Polylines**: Minimal memory (temporary generation) ### CPU Performance **Bottlenecks** (in order of impact): 1. **OpenAP Calculations**: Flight profile generation (200-500ms) 2. **Geodesic Calculations**: Route sampling (10-50ms) 3. **Airport Search**: City name fuzzy matching (1-5ms) 4. **JSON Serialization**: Pydantic model conversion (1-2ms) **Optimization Strategies**: - Cache OpenAP aircraft properties - Optimize route sampling resolution - Pre-compute common city-airport mappings - Use more efficient JSON serialization ### Scalability Metrics Current single-threaded performance estimates: - **Health checks**: 10,000+ req/sec - **Airport searches**: 1,000+ req/sec - **Flight planning**: 5-10 req/sec (OpenAP-limited) **Scaling Strategies**: ```mermaid graph TB Current[Single Process] --> Horizontal[Horizontal Scaling] Current --> Vertical[Vertical Scaling] Current --> Async[Async Processing] Horizontal --> LoadBalancer[Load Balancer] Horizontal --> MultiInstance[Multiple Instances] Vertical --> MoreCPU[More CPU Cores] Vertical --> MoreRAM[More RAM] Async --> Celery[Celery Workers] Async --> AsyncFramework[Async Framework] ``` ## Security Considerations ### Current Security Posture **Authentication**: None (suitable for development/internal use) **Authorization**: None (open access to all endpoints) **Input Validation**: Pydantic models with type checking **Rate Limiting**: None (could lead to resource exhaustion) ### Production Security Enhancements #### 1. Authentication & Authorization ```python # Example JWT implementation from fastapi.security import HTTPBearer from jose import jwt security = HTTPBearer() @app.dependency async def get_current_user(token: str = Depends(security)): payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) return payload["sub"] @app.post("/plan", dependencies=[Depends(get_current_user)]) def plan(req: PlanRequest): # Protected endpoint pass ``` #### 2. Input Sanitization ```python class PlanRequest(BaseModel): depart_city: str = Field(..., min_length=2, max_length=100, regex=r'^[a-zA-Z\s]+$') ac_type: str = Field(..., regex=r'^[A-Z0-9]{3,4}$') # ICAO format ``` #### 3. Rate Limiting ```python from slowapi import Limiter limiter = Limiter(key_func=get_remote_address) @app.post("/plan") @limiter.limit("10/minute") def plan(request: Request, req: PlanRequest): pass ``` #### 4. HTTPS/TLS ```bash # Production deployment with TLS uvicorn main:app --host 0.0.0.0 --port 443 \ --ssl-keyfile key.pem --ssl-certfile cert.pem ``` ### Data Privacy **No PII Collection**: System doesn't collect personal information **Audit Logging**: Consider logging for flight planning requests **Data Retention**: No persistent storage of user requests ## Scalability & Future Enhancements ### Horizontal Scaling Architecture ```mermaid graph TB LB[Load Balancer] --> App1[App Instance 1] LB --> App2[App Instance 2] LB --> AppN[App Instance N] App1 --> Cache[Redis Cache] App2 --> Cache AppN --> Cache App1 --> DB[(Airport Database)] App2 --> DB AppN --> DB subgraph "Background Workers" Worker1[Performance Worker 1] Worker2[Performance Worker 2] WorkerN[Performance Worker N] end App1 --> Queue[Task Queue] App2 --> Queue AppN --> Queue Queue --> Worker1 Queue --> Worker2 Queue --> WorkerN ``` ### Database Migration Strategy **Phase 1**: Add optional database support alongside in-memory ```python if DATABASE_URL: airports = load_from_database() else: airports = airportsdata.load("IATA") # Fallback ``` **Phase 2**: Implement caching layer ```python @cache(ttl=3600) # 1-hour cache def find_city_airports(city: str, country: Optional[str]): return db.query_airports(city, country) ``` **Phase 3**: Full database migration with real-time updates ### Enhanced Features Roadmap #### 1. Weather Integration ```python class PlanRequest(BaseModel): include_weather: bool = False weather_source: Literal["noaa", "openweather"] = "noaa" # Weather-adjusted performance calculations def estimates_with_weather(ac_type, route, weather_data): # Adjust for winds, temperature, turbulence pass ``` #### 2. NOTAM Integration ```python @app.get("/route/{flight_id}/notams") def get_route_notams(flight_id: str): # Return NOTAMs affecting the route pass ``` #### 3. Multi-leg Flight Planning ```python class MultiLegRequest(BaseModel): waypoints: List[str] # City names or IATA codes aircraft: str stopovers: List[StopoverConfig] = [] class StopoverConfig(BaseModel): min_ground_time: int = 45 # minutes fuel_stop: bool = False passenger_stop: bool = True ``` #### 4. Real-time Flight Tracking ```python @app.websocket("/ws/track/{flight_id}") async def track_flight(websocket: WebSocket, flight_id: str): # Real-time position updates pass ``` ### Performance Optimization Roadmap #### 1. Caching Strategy - **L1 Cache**: In-memory LRU cache for common requests - **L2 Cache**: Redis for shared cache across instances - **L3 Cache**: CDN for static airport data #### 2. Database Optimization - **Indexing**: Spatial indexes for airport coordinates - **Partitioning**: Partition by region/country - **Read Replicas**: Separate read/write workloads #### 3. Async Processing ```python @app.post("/plan/async") async def plan_async(req: PlanRequest): task_id = await queue_flight_plan.delay(req) return {"task_id": task_id} @app.get("/plan/status/{task_id}") async def get_plan_status(task_id: str): return await get_task_status(task_id) ``` ### Monitoring & Observability ```mermaid graph LR App[Application] --> Metrics[Metrics Collector] App --> Logs[Log Aggregator] App --> Traces[Distributed Tracing] Metrics --> Prometheus[Prometheus] Logs --> ELK[ELK Stack] Traces --> Jaeger[Jaeger] Prometheus --> Grafana[Grafana Dashboard] ELK --> Kibana[Kibana Dashboard] Jaeger --> UI[Jaeger UI] ``` **Key Metrics to Monitor**: - Request latency (p50, p95, p99) - Error rates by endpoint - OpenAP calculation time - Memory usage trends - Cache hit rates **Alerting Thresholds**: - Response time > 5 seconds - Error rate > 5% - Memory usage > 80% - OpenAP unavailable This architecture provides a solid foundation for the current requirements while maintaining flexibility for future enhancements and scaling needs.

Latest Blog Posts

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/cheesejaguar/aerospace-mcp'

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