master
c 280 lines 13.5 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 /**
4 * MCP Initialize Method
5 *
6 * The initialize method is a core part of the Model Context Protocol (MCP),
7 * serving as the initial handshake between client and server.
8 *
9 * According to the MCP specification:
10 *
11 * 1. Purpose:
12 * - Establishes the protocol version to use for communication
13 * - Provides information about server capabilities
14 * - Exchanges client and server metadata
15 * - Sets up the foundation for subsequent interactions
16 *
17 * 2. Protocol flow:
18 * - The client sends an initialize request with its supported protocol version
19 * - The server responds with its capabilities and selected protocol version
20 * - After successful initialization, other methods become available
21 *
22 * 3. Key components in the response:
23 * - protocolVersion: The protocol version the server will use
24 * - capabilities: A structured object describing supported features
25 * - serverInfo: Information about the server implementation
26 *
27 * This method must be called before any other MCP method, and handles
28 * protocol version negotiation and capability discovery.
29 */
30
31 #include "mcp-initialize.h"
32 #include "database/rrd-metadata.h"
33 #include "daemon/common.h"
34
35 // Initialize handler - provides information about what's available (transport-agnostic)
36 MCP_RETURN_CODE mcp_method_initialize(MCP_CLIENT *mcpc, struct json_object *params, MCP_REQUEST_ID id) {
37 if (!mcpc)
38 return MCP_RC_ERROR;
39
40 // Extract client's requested protocol version
41 struct json_object *protocol_version_obj = NULL;
42 if (json_object_object_get_ex(params, "protocolVersion", &protocol_version_obj)) {
43 const char *version_str = json_object_get_string(protocol_version_obj);
44
45 // Convert to our enum
46 mcpc->protocol_version = MCP_PROTOCOL_VERSION_2id(version_str);
47
48 // If unknown version, default to the latest we support
49 if (mcpc->protocol_version == MCP_PROTOCOL_VERSION_UNKNOWN) {
50 mcpc->protocol_version = MCP_PROTOCOL_VERSION_LATEST;
51 }
52 } else {
53 // No version specified, default to oldest version for compatibility
54 mcpc->protocol_version = MCP_PROTOCOL_VERSION_2024_11_05;
55 }
56
57 netdata_log_debug(D_MCP, "MCP initialize request from client %s version %s, protocol version %s",
58 string2str(mcpc->client_name), string2str(mcpc->client_version),
59 MCP_PROTOCOL_VERSION_2str(mcpc->protocol_version));
60
61 // Initialize result buffer with JSON structure
62 mcp_init_success_result(mcpc, id);
63
64 // Use rrdstats_metadata_collect to get infrastructure statistics
65 RRDSTATS_METADATA metadata = rrdstats_metadata_collect();
66
67 // Add protocol version based on what client requested
68 buffer_json_member_add_string(mcpc->result, "protocolVersion",
69 MCP_PROTOCOL_VERSION_2str(mcpc->protocol_version));
70
71 // Add server info object
72 buffer_json_member_add_object(mcpc->result, "serverInfo");
73 buffer_json_member_add_string(mcpc->result, "name", "Netdata");
74 buffer_json_member_add_string(mcpc->result, "version", NETDATA_VERSION);
75 buffer_json_object_close(mcpc->result); // Close serverInfo
76
77 // Add capabilities object according to MCP standard
78 buffer_json_member_add_object(mcpc->result, "capabilities");
79
80 // Tools capabilities
81 buffer_json_member_add_object(mcpc->result, "tools");
82 buffer_json_member_add_boolean(mcpc->result, "listChanged", false);
83 buffer_json_member_add_boolean(mcpc->result, "asyncExecution", true);
84 buffer_json_member_add_boolean(mcpc->result, "batchExecution", true);
85 buffer_json_object_close(mcpc->result); // Close tools
86
87 // Resources capabilities
88 buffer_json_member_add_object(mcpc->result, "resources");
89 buffer_json_member_add_boolean(mcpc->result, "listChanged", true);
90 buffer_json_member_add_boolean(mcpc->result, "subscribe", true);
91 buffer_json_object_close(mcpc->result); // Close resources
92
93 // Prompts capabilities
94 buffer_json_member_add_object(mcpc->result, "prompts");
95 buffer_json_member_add_boolean(mcpc->result, "listChanged", false);
96 buffer_json_object_close(mcpc->result); // Close prompts
97
98 // Notification capabilities
99 buffer_json_member_add_object(mcpc->result, "notifications");
100 buffer_json_member_add_boolean(mcpc->result, "push", true);
101 buffer_json_member_add_boolean(mcpc->result, "subscription", true);
102 buffer_json_object_close(mcpc->result); // Close notifications
103
104 // Add logging capabilities
105 buffer_json_member_add_object(mcpc->result, "logging");
106 buffer_json_object_close(mcpc->result); // Close logging
107
108 // Add version-specific capabilities
109 if (mcpc->protocol_version >= MCP_PROTOCOL_VERSION_2025_03_26) {
110 // Add completions capability - new in 2025-03-26
111 buffer_json_member_add_object(mcpc->result, "completions");
112 buffer_json_object_close(mcpc->result); // Close completions
113 }
114
115 buffer_json_object_close(mcpc->result); // Close capabilities
116
117 // Add dynamic instructions based on server profile
118 char instructions[8192];
119
120 const char *instructions_template =
121 "This is %s.\n"
122 "\n"
123 "## NETDATA'S UNIQUE CAPABILITIES\n"
124 "\n"
125 "### Real-Time Anomaly Detection\n"
126 "Netdata performs ML-based anomaly detection (k-means clustering) on every metric during data collection. "
127 "Each sample includes its anomaly status from when it was originally collected.\n"
128 "\n"
129 "**Critical: Anomaly Rate Interpretation**\n"
130 "- Low percentages often indicate major events, not noise\n"
131 "- Time window context is essential:\n"
132 " • 1%% over 1 hour = ~36 seconds of anomalies (minor)\n"
133 " • 1%% over 1 day = ~14 minutes of anomalies (moderate)\n"
134 " • 1%% over 1 week = ~2 hours of anomalies (potentially major incident)\n"
135 "- Anomalies may be concentrated in time, indicating real events\n"
136 "- Always query actual metrics to see anomaly distribution across data points\n"
137 "- The ML model detected these anomalies in real-time without future knowledge\n"
138 "\n"
139 "## TOOL ARCHITECTURE AND PATTERNS\n"
140 "\n"
141 "### Pattern Matching Rules\n"
142 "**Discovery tools** (list_metrics, list_nodes, list_running_alerts) support patterns on their PRIMARY data:\n"
143 "- `list_metrics`: patterns on metric names (e.g., 'system.*', '*nginx*')\n"
144 "- `list_nodes`: patterns on hostnames (e.g., '*web*', 'prod-*')\n"
145 "- Secondary parameters (nodes, metrics) require EXACT names only\n"
146 "\n"
147 "**Query tools** (query_metrics, find_*_metrics) require EXACT names for ALL parameters:\n"
148 "- No patterns allowed - you must specify exact metric names\n"
149 "- Use discovery tools first to get exact names, then query\n"
150 "\n"
151 "### Tool Combination Strategy\n"
152 "Tools are designed to work together. Use outputs from one tool as inputs to others:\n"
153 "\n"
154 "**Example: Find nodes running specific services**\n"
155 "```\n"
156 "1. list_metrics (pattern: '*redis*') → get exact context names\n"
157 "2. list_nodes (metrics: ['redis.connections', 'redis.memory']) → get only nodes running redis\n"
158 "```\n"
159 "\n"
160 "**Example: Investigate performance issues**\n"
161 "```\n"
162 "1. find_anomalous_metrics (timeframe) → identify problematic metrics\n"
163 "2. query_metrics (exact metric names from step 1) → see detailed data\n"
164 "3. find_correlated_metrics (same timeframe) → what changed significantly during this period\n"
165 "```\n"
166 "\n"
167 "## INVESTIGATION METHODOLOGY\n"
168 "\n"
169 "### Discovery Workflow\n"
170 "Follow the data trail using these interactive tools:\n"
171 "\n"
172 "**For \"What's available\" questions:**\n"
173 "- `list_metrics`: Full-text search (use 'q' parameter) or pattern matching\n"
174 "- `list_nodes`: Search by hostname patterns or filter by exact metric names\n"
175 "- `get_metrics_details`: Get comprehensive information about specific metrics\n"
176 "\n"
177 "**For incident investigation:**\n"
178 "- `find_anomalous_metrics`: Discover ML-detected anomalies in any timeframe\n"
179 "- `find_correlated_metrics`: Find metrics that changed significantly during a time period\n"
180 " (compares against 4x previous baseline to score changes)\n"
181 "- `list_alert_transitions`: See how alerts changed state during incidents\n"
182 "- `query_metrics`: Get detailed time-series data with per-point anomaly information\n"
183 "\n"
184 "**For current system state:**\n"
185 "- `execute_function`: Get live information (processes, connections, services)\n"
186 "- `list_raised_alerts`: See currently active alerts requiring attention\n"
187 "\n"
188 "### Investigation Flow\n"
189 "1. **Start with discovery**: Use broad searches to identify relevant components\n"
190 "2. **Get exact names**: Convert patterns to exact metric/node names\n"
191 "3. **Query for details**: Use exact names in query tools for deep analysis\n"
192 "4. **Follow connections**: When data reveals related areas, investigate them\n"
193 "5. **Reach conclusions**: Stop when you have sufficient information to answer comprehensively\n"
194 "\n"
195 "### Tool Response Patterns\n"
196 "- **Categorized responses**: When results exceed limits, tools group by category\n"
197 " Use specific patterns (e.g., 'system.*') to get full details for categories\n"
198 "- **Error guidance**: Tools provide specific instructions when parameters are incorrect\n"
199 "- **Next steps**: Many responses include suggested follow-up actions\n"
200 "- **Batch execution**: Run multiple tools in parallel for efficiency\n"
201 "\n"
202 "## PRACTICAL EXAMPLES\n"
203 "\n"
204 "**Infrastructure discovery:**\n"
205 "```\n"
206 "User: \"What databases are being monitored?\"\n"
207 "1. list_metrics (q: \"*mysql*|*postgres*|*redis*|*mongo*\")\n"
208 "2. get_metrics_details for interesting database contexts\n"
209 "3. list_nodes (metrics: exact database context names) → nodes running databases\n"
210 "```\n"
211 "\n"
212 "**Performance troubleshooting:**\n"
213 "```\n"
214 "User: \"System was slow yesterday 2-4 PM\"\n"
215 "1. find_anomalous_metrics (yesterday 14:00-16:00)\n"
216 "2. query_metrics (exact anomalous metric names) → see concentration patterns\n"
217 "3. find_correlated_metrics (same timeframe) → what changed significantly during this period\n"
218 "4. execute_function (if issues persist) → check current state\n"
219 "```\n"
220 "\n"
221 "**Service-specific analysis:**\n"
222 "```\n"
223 "User: \"How is nginx performing?\"\n"
224 "1. list_metrics (q: \"*nginx*\") → get all nginx-related contexts\n"
225 "2. list_nodes (metrics: nginx contexts) → find nginx servers\n"
226 "3. query_metrics (nginx metrics, specific nodes) → analyze performance\n"
227 "4. list_running_alerts (metrics: nginx contexts) → check for issues\n"
228 "```\n"
229 "\n"
230 "Remember: Netdata's per-second resolution and real-time anomaly detection provide "
231 "unprecedented visibility into system behavior. Use tool combinations to build a "
232 "complete picture from discovery through detailed analysis.\n"
233 "\n"
234 "### Infrastructure-Wide Anomaly Correlation\n"
235 "For multi-node infrastructures, this single query reveals cascading anomalies across all nodes:\n"
236 "\n"
237 "```\n"
238 "query_metrics(\n"
239 " metric: \"anomaly_detection.dimensions\",\n"
240 " dimensions: [\"anomalous\"],\n"
241 " after: <timeframe>,\n"
242 " before: <timeframe>,\n"
243 " points: <based_on_duration>,\n"
244 " time_group: \"max\",\n"
245 " group_by: [\"node\"],\n"
246 " aggregation: \"max\"\n"
247 ")\n"
248 "```\n"
249 "\n"
250 "This returns the COUNT of dimensions (time-series) that were anomalous SIMULTANEOUSLY on each node.\n"
251 "\n"
252 "The resulting time-series shows anomaly propagation patterns:\n"
253 "- **Simultaneous spikes across nodes** = External event (network outage, DNS, etc.)\n"
254 "- **Sequential spikes with delays** = Cascading failure showing dependencies\n"
255 "- **Isolated node spikes** = Node-specific issues\n"
256 "\n"
257 "The time-series visualization immediately reveals which nodes were affected and in what order - "
258 "critical for root cause analysis in distributed systems.\n"
259 "\n"
260 "After identifying the cascade pattern, use find_anomalous_metrics on specific nodes/times for details.";
261
262 // Determine server role and create complete instructions
263 if (metadata.nodes.total > 1) {
264 snprintfz(instructions, sizeof(instructions), instructions_template,
265 "a Netdata Parent Server hosting metrics and logs for multiple nodes");
266 } else {
267 snprintfz(instructions, sizeof(instructions), instructions_template,
268 "Netdata on a standalone server");
269 }
270
271 buffer_json_member_add_string(mcpc->result, "instructions", instructions);
272
273 // Add _meta field (optional) - empty as requested
274 buffer_json_member_add_object(mcpc->result, "_meta");
275 buffer_json_object_close(mcpc->result); // Close _meta
276 buffer_json_object_close(mcpc->result); // Close result object
277 buffer_json_finalize(mcpc->result); // Finalize JSON
278
279 return MCP_RC_OK;
280 }