| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #ifndef NETDATA_MCP_TOOLS_EXECUTE_FUNCTION_INTERNAL_H |
| 4 | #define NETDATA_MCP_TOOLS_EXECUTE_FUNCTION_INTERNAL_H |
| 5 | |
| 6 | #include "mcp.h" |
| 7 | #include "database/contexts/rrdcontext.h" |
| 8 | |
| 9 | // Pagination units enumeration - only supported types enable cursor pagination |
| 10 | typedef enum mcp_pagination_units { |
| 11 | MCP_PAGINATION_UNITS_UNKNOWN = 0, // Unknown units - pagination disabled |
| 12 | MCP_PAGINATION_UNITS_TIMESTAMP_USEC, // Microsecond timestamps |
| 13 | } MCP_PAGINATION_UNITS; |
| 14 | |
| 15 | // Define operator types for faster comparison |
| 16 | typedef enum { |
| 17 | OP_EQUALS, // == |
| 18 | OP_NOT_EQUALS, // != or <> |
| 19 | OP_LESS, // < |
| 20 | OP_LESS_EQUALS, // <= |
| 21 | OP_GREATER, // > |
| 22 | OP_GREATER_EQUALS, // >= |
| 23 | OP_MATCH, // simple pattern |
| 24 | OP_NOT_MATCH, // a negative match of a simple pattern |
| 25 | OP_UNKNOWN // unknown operator |
| 26 | } OPERATOR_TYPE; |
| 27 | |
| 28 | // Maximum number of conditions we expect to handle |
| 29 | #define MAX_CONDITIONS 20 |
| 30 | #define MAX_COLUMNS 300 // Maximum number of columns we can handle |
| 31 | #define MAX_SELECTED_COLUMNS 100 // Maximum number of columns that can be selected |
| 32 | |
| 33 | // Result status for table processing |
| 34 | typedef enum { |
| 35 | MCP_TABLE_OK, // Success |
| 36 | MCP_TABLE_ERROR_INVALID_CONDITIONS, // Condition format/parsing error |
| 37 | MCP_TABLE_ERROR_NO_MATCHES_WITH_MISSING_COLUMNS, // No matches, some columns not found |
| 38 | MCP_TABLE_ERROR_NO_MATCHES, // No matches with valid columns |
| 39 | MCP_TABLE_ERROR_INVALID_SORT_ORDER, // Invalid sort order parameter |
| 40 | MCP_TABLE_ERROR_COLUMNS_NOT_FOUND, // Requested columns not found |
| 41 | MCP_TABLE_ERROR_SORT_COLUMN_NOT_FOUND, // Sort column not found |
| 42 | MCP_TABLE_ERROR_TOO_MANY_COLUMNS, // Exceeds MAX_COLUMNS |
| 43 | MCP_TABLE_NOT_JSON, // Response is not valid JSON |
| 44 | MCP_TABLE_NOT_PROCESSABLE, // JSON but not a processable table format |
| 45 | MCP_TABLE_EMPTY_RESULT, // Function returned no rows |
| 46 | MCP_TABLE_INFO_MISSING_COLUMNS_FOUND_RESULTS, // Missing columns but found via wildcard |
| 47 | MCP_TABLE_RESPONSE_TOO_BIG // Result too big, guidance added |
| 48 | } MCP_TABLE_RESULT_STATUS; |
| 49 | |
| 50 | // Function response types |
| 51 | typedef enum { |
| 52 | FN_TYPE_UNKNOWN = 0, |
| 53 | FN_TYPE_TABLE, // Regular table (has_history=false) |
| 54 | FN_TYPE_TABLE_WITH_HISTORY, // Logs table (has_history=true) |
| 55 | FN_TYPE_NOT_TABLE // Not a table format |
| 56 | } MCP_FUNCTION_TYPE; |
| 57 | |
| 58 | // Value types for conditions |
| 59 | typedef enum { |
| 60 | COND_VALUE_STRING, |
| 61 | COND_VALUE_NUMBER, |
| 62 | COND_VALUE_BOOLEAN, |
| 63 | COND_VALUE_NULL |
| 64 | } CONDITION_VALUE_TYPE; |
| 65 | |
| 66 | // Structure to hold preprocessed condition information |
| 67 | typedef struct condition_s { |
| 68 | int column_index; // Index of the column in the row (-1 for wildcard search) |
| 69 | const char *column_name; // Name of the column (referenced from json-c, not owned) |
| 70 | OPERATOR_TYPE op; // Operator type |
| 71 | CONDITION_VALUE_TYPE v_type; // Type of the value |
| 72 | union { |
| 73 | const char *v_str; // String value (referenced from json-c, not owned) |
| 74 | bool v_bool; // Boolean value |
| 75 | double v_num; // Numeric value (using double to handle both int and float) |
| 76 | }; |
| 77 | SIMPLE_PATTERN *pattern; // Pre-compiled pattern for MATCH operations (owned - must be freed) |
| 78 | } CONDITION; |
| 79 | |
| 80 | // Structure to hold an array of conditions |
| 81 | typedef struct { |
| 82 | CONDITION items[MAX_CONDITIONS]; // Fixed array of conditions |
| 83 | size_t count; // Number of conditions currently in use |
| 84 | bool has_missing_columns; // True if any column was not found |
| 85 | } CONDITION_ARRAY; |
| 86 | |
| 87 | // Structure to hold function data throughout processing |
| 88 | typedef struct { |
| 89 | // Request context - all parsed parameters |
| 90 | struct { |
| 91 | // Core request data |
| 92 | MCP_CLIENT *mcpc; // The MCP client |
| 93 | struct json_object *params; // The raw parameters as given by the client |
| 94 | |
| 95 | // Parsed required parameters |
| 96 | const char *function; // Function name to execute |
| 97 | const char *node; // Node name/id/guid |
| 98 | RRDHOST *host; // The resolved host |
| 99 | time_t timeout; // Timeout in seconds |
| 100 | |
| 101 | // Transaction tracking |
| 102 | nd_uuid_t transaction_uuid; // Transaction UUID |
| 103 | char transaction[UUID_STR_LEN]; // Transaction UUID string |
| 104 | |
| 105 | // Authentication |
| 106 | USER_AUTH *auth; // User authentication info |
| 107 | |
| 108 | // Parsed optional parameters for table filtering |
| 109 | struct { |
| 110 | const char *column; // Column to sort by (referenced from json-c, not owned) |
| 111 | bool descending; // true for DESC, false for ASC |
| 112 | } sort; // Sort configuration |
| 113 | |
| 114 | size_t limit; // Row limit (0 = no limit) |
| 115 | struct { |
| 116 | const char *array[MAX_SELECTED_COLUMNS]; // Column names to include (referenced from json-c, not owned) |
| 117 | size_t count; // Number of columns selected |
| 118 | } columns; // Selected columns |
| 119 | |
| 120 | CONDITION_ARRAY conditions; // Preprocessed conditions |
| 121 | |
| 122 | // Time-based and history parameters |
| 123 | time_t after; // Start time for the query (0 = not specified) |
| 124 | time_t before; // End time for the query (0 = not specified) |
| 125 | const char *cursor; // Pagination cursor (MCP standard) (referenced from json-c, not owned) |
| 126 | usec_t anchor; // Internal anchor timestamp converted from cursor (0 = not specified) |
| 127 | const char *direction; // Query direction: "forward" or "backward" (referenced from json-c, not owned) |
| 128 | const char *query; // Full-text search query (referenced from json-c, not owned) |
| 129 | } request; |
| 130 | |
| 131 | // Pagination settings (copied from registry_entry to avoid keeping it locked) |
| 132 | struct { |
| 133 | bool enabled; // whether pagination is supported |
| 134 | MCP_PAGINATION_UNITS units; // units of the pagination column |
| 135 | STRING *column; // column name in data (owned copy) |
| 136 | } pagination; |
| 137 | |
| 138 | // Input data from the function |
| 139 | struct { |
| 140 | struct json_object *jobj; // The parsed JSON object |
| 141 | BUFFER *json; // The original JSON response |
| 142 | MCP_FUNCTION_TYPE type; // Type of response |
| 143 | size_t rows; // Number of rows in original data |
| 144 | size_t columns; // Number of columns available |
| 145 | } input; |
| 146 | |
| 147 | // Output data after processing |
| 148 | struct { |
| 149 | MCP_TABLE_RESULT_STATUS status; // Result of processing |
| 150 | BUFFER *result; // Response to send to the client |
| 151 | size_t rows; // Number of rows after filtering |
| 152 | size_t columns; // Number of columns selected |
| 153 | } output; |
| 154 | } MCP_FUNCTION_DATA; |
| 155 | |
| 156 | // Function prototypes shared between execute-function and execute-function-logs |
| 157 | |
| 158 | // Initialize MCP_FUNCTION_DATA structure |
| 159 | void mcp_functions_data_init(MCP_FUNCTION_DATA *data); |
| 160 | |
| 161 | // Clean up MCP_FUNCTION_DATA structure |
| 162 | void mcp_functions_data_cleanup(MCP_FUNCTION_DATA *data); |
| 163 | |
| 164 | // Analyze the JSON response and determine its type |
| 165 | MCP_FUNCTION_TYPE mcp_functions_analyze_response(struct json_object *json_obj, int *out_status); |
| 166 | |
| 167 | // Convert string operator to enum type |
| 168 | OPERATOR_TYPE mcp_functions_string_to_operator(const char *op_str); |
| 169 | |
| 170 | // Free patterns in the condition array |
| 171 | void mcp_functions_free_condition_patterns(CONDITION_ARRAY *condition_array); |
| 172 | |
| 173 | #endif // NETDATA_MCP_TOOLS_EXECUTE_FUNCTION_INTERNAL_H |