Skip to main content
Glama
croit
by croit
ARCHITECTURE.api-request-execution.md11 kB
# API Request Execution ## Overview The API request execution workflow handles the complete lifecycle of an API call from tool invocation to optimized response delivery. It integrates token optimization, schema validation, and error handling. **Module**: mcp-croit-ceph.py **Methods**: `handle_hybrid_tool()`, `_call_endpoint_direct()`, `_make_api_call()` **Duration**: 100-2000ms per request ## Purpose Executes API requests with: - Parameter validation and transformation - Token optimization - Response filtering - Error handling and propagation - Metadata enrichment ## Execution Flow ### Complete Request Lifecycle ``` LLM Tool Invocation ↓ Mode-Specific Handler ├── hybrid → handle_hybrid_tool() ├── base_only → handle_api_call_tool() └── categories_only → handle_category_tool() ↓ Route to Appropriate Handler ├── Base tools → _list_endpoints_filtered() │ _call_endpoint_direct() │ _quick_find_endpoints() ├── Category tools → _handle_category_tool() └── Log tools → _handle_log_search() ↓ Parameter Processing ├── Extract endpoint path ├── Extract HTTP method ├── Extract body/query parameters ├── Apply default pagination └── Validate required fields ↓ Token Optimization (Pre-Request) ├── should_optimize()? ├── add_default_limit() └── Note: filters for post-processing ↓ HTTP Request Execution (_make_api_call) ├── Build full URL ├── Add authorization header ├── Set SSL verification ├── Execute with aiohttp └── Handle HTTP errors ↓ Response Processing ├── Parse JSON ├── Check for API errors └── Extract data ↓ Token Optimization (Post-Response) ├── truncate_response() ├── apply_filters() └── Add metadata ↓ Return to LLM ``` ## Handler Methods ### `handle_hybrid_tool(name, arguments)` Routes hybrid mode tool invocations. **Logic**: ```python if name in ["list_endpoints", "call_endpoint", "get_schema"]: # Base tools return await base_tool_handler(name, arguments) elif name.startswith("manage_"): # Category tools category = name.replace("manage_", "") return await _handle_category_tool(category, arguments) elif name in ["croit_log_search", "croit_log_check"]: # Log tools return await log_tool_handler(name, arguments) else: raise ValueError(f"Unknown tool: {name}") ``` ### `_call_endpoint_direct(arguments)` Executes direct API endpoint calls. **Input Arguments**: ```python { "endpoint_path": "/api/services", "method": "GET", # Optional, default: GET "query_params": {...}, # Optional "body_params": {...}, # Optional "path_params": {...} # Optional for templates } ``` **Processing Steps**: 1. Extract and validate endpoint path 2. Determine HTTP method (default: GET from spec) 3. Process path parameters (replace {id} templates) 4. Merge query parameters 5. Build request body 6. Apply token optimization 7. Execute request 8. Process response ### `_handle_category_tool(category, arguments)` Handles category-specific tool invocations. **Input Arguments**: ```python { "action": "list|get|create|update|delete", "action_args": {...}, # Action-specific parameters "server_id": "...", # Context-dependent "resource_id": "...", # For get/update/delete "filters": {...} # For list operations } ``` **Action Routing**: ```python if action == "list": endpoint = find_list_endpoint(category) method = "GET" params = action_args + default_pagination elif action == "get": endpoint = find_get_endpoint(category) method = "GET" params = {"id": resource_id} elif action == "create": endpoint = find_create_endpoint(category) method = "POST" body = action_args elif action == "update": endpoint = find_update_endpoint(category) method = "PUT" or "PATCH" body = action_args elif action == "delete": endpoint = find_delete_endpoint(category) method = "DELETE" params = {"id": resource_id} ``` ## HTTP Request Execution ### `_make_api_call(endpoint_path, method, params, body)` Low-level HTTP execution. **Request Construction**: ```python url = f"{self.host}{endpoint_path}" headers = { "Authorization": f"Bearer {self.api_token}", "Content-Type": "application/json" } # Apply SSL verification verify_ssl = self.ssl # Execute with aiohttp async with self.session.request( method=method, url=url, params=params, json=body, headers=headers, ssl=verify_ssl ) as response: data = await response.json() return data ``` **Error Handling**: - 4xx errors → API error message to LLM - 5xx errors → Server error message to LLM - Network errors → Connection error to LLM - Timeout → Timeout error to LLM ## Token Optimization Integration ### Pre-Request Optimization **Method**: `TokenOptimizer.add_default_limit()` Applied to GET requests on list endpoints: ```python if TokenOptimizer.should_optimize(url, method): params = TokenOptimizer.add_default_limit(url, params) ``` **Default Limits**: - Services/servers: limit=25 - OSDs: limit=30 - Stats: limit=50 - Logs: limit=100 - General: limit=10 ### Post-Response Optimization **Method**: `TokenOptimizer.truncate_response()` Applied to all list responses: ```python if isinstance(response_data, list) and len(response_data) > max_items: response_data = TokenOptimizer.truncate_response(response_data, url) ``` **Result**: ```python { "data": [truncated items], "_truncation_metadata": { "truncated": true, "original_count": 500, "returned_count": 25, "truncation_message": "..." } } ``` ### Filter Application **Method**: `TokenOptimizer.apply_filters()` Applied when `_filter_*` parameters present: ```python filters = extract_filters(params) # _filter_status, _filter_name, etc. if filters: response_data = TokenOptimizer.apply_filters(response_data, filters) ``` ## Parameter Processing ### Query Parameter Handling **Standard Parameters**: - `limit`, `offset`: Pagination - `sort`, `order`: Sorting - `filter`: Generic filtering **Filter Parameters** (custom): - `_filter_status=error`: Exact match - `_filter_name=~ceph.*`: Regex - `_filter_size=>1000`: Numeric comparison - `_filter__text=timeout`: Full-text search - `_filter__has=error_message`: Field existence **Processing**: ```python def extract_filters(params): filters = {} for key, value in params.items(): if key.startswith("_filter_"): field = key.replace("_filter_", "") filters[field] = value del params[key] # Remove from query params return filters ``` ### Body Parameter Handling **For POST/PUT/PATCH**: ```python body = arguments.get("body_params", {}) # Validate required fields from OpenAPI schema # Apply defaults # Convert types as needed ``` ### Path Parameter Handling **Template Replacement**: ```python path_params = arguments.get("path_params", {}) for key, value in path_params.items(): endpoint_path = endpoint_path.replace(f"{{{key}}}", str(value)) # Example: "/servers/{id}/disks" + {"id": "1"} → "/servers/1/disks" ``` ## Response Processing ### Success Response **Standard Format**: ```python { "data": [...], # or single object "metadata": { "count": 100, "limit": 25, "offset": 0 } } ``` **Processed Format**: ```python { "data": [...], # Potentially truncated "_optimization_applied": true, "_original_count": 100, "_returned_count": 25, "_truncation_metadata": {...} # If truncated } ``` ### Error Response **API Error**: ```python { "error": { "code": "RESOURCE_NOT_FOUND", "message": "Server with ID 999 not found", "details": {...} } } ``` **Passed to LLM as**: ```python { "error": "API Error: Server with ID 999 not found", "error_code": "RESOURCE_NOT_FOUND", "suggestion": "Check server ID and try again" } ``` ## Pagination Handling ### Automatic Pagination **Detection**: ```python def _endpoint_requires_pagination(endpoint_path): # Check if endpoint typically returns lists return any(indicator in endpoint_path for indicator in [ "/list", "/all", "get_all" ]) ``` **Default Pagination**: ```python def _get_default_pagination(category): if category in ["logs", "audit"]: return {"limit": 100, "offset": 0} elif category in ["services", "servers"]: return {"limit": 25, "offset": 0} else: return {"limit": 10, "offset": 0} ``` ### Manual Pagination **User-Specified**: ```python { "query_params": { "limit": 50, "offset": 100 } } ``` **Overrides**: User-specified values override automatic defaults ## Error Handling Strategy ### Retry Logic **Transient Errors** (retried): - Connection timeout (max 3 retries) - 503 Service Unavailable (exponential backoff) - Network connection reset **Permanent Errors** (not retried): - 400 Bad Request - 401 Unauthorized - 403 Forbidden - 404 Not Found ### Error Enrichment **Context Added**: ```python { "error": "Original error message", "endpoint": "/api/services", "method": "GET", "suggestion": "Check authentication token", "related_hints": [...] # From x-llm-hints } ``` ## Performance Characteristics **Typical Timing**: - Parameter processing: 1-5ms - HTTP request: 50-500ms - Response parsing: 5-20ms - Token optimization: 10-100ms - **Total**: 100-700ms **With Truncation**: - Large response (1000 items): +50-200ms - Filter application: +10-50ms per filter ## Caching Considerations **No Built-In Caching** for API calls: - Every request hits the cluster - Ensures fresh data - Allows real-time updates **Log Search Caching**: - 5-minute cache for log queries - Separate from API request flow ## Design Patterns **Template Method**: Common execution structure with customization points **Chain of Responsibility**: Error handling propagation **Decorator Pattern**: Token optimization wrapping **Strategy Pattern**: Mode-specific routing ## Extension Points 1. **Custom Handlers**: Add to mode routing logic 2. **Optimization Strategies**: Extend TokenOptimizer integration 3. **Error Handling**: Add custom error processors 4. **Response Transformers**: Post-processing pipelines 5. **Caching Layer**: Add response caching ## Relevance Read this document when: - Understanding request execution flow - Debugging API call issues - Implementing custom handlers - Optimizing request performance - Adding new token optimization strategies - Troubleshooting parameter handling ## Related Documentation - [ARCHITECTURE.token-optimizer.md](ARCHITECTURE.token-optimizer.md) - Optimization logic - [ARCHITECTURE.response-filtering.md](ARCHITECTURE.response-filtering.md) - Filter details - [ARCHITECTURE.mcp-protocol-handlers.md](ARCHITECTURE.mcp-protocol-handlers.md) - Handler registration - [ARCHITECTURE.croit-api-rest-interface.md](ARCHITECTURE.croit-api-rest-interface.md) - API interface

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/croit/mcp-croit-ceph'

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