master
c 93 lines 3.57 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 /**
4 * MCP Logging Namespace
5 *
6 * The MCP Logging namespace provides methods for controlling server logging behavior.
7 * In the MCP protocol, logging methods allow clients to control the verbosity
8 * of logging information shared by the server through notifications.
9 *
10 * Standard methods in the MCP specification:
11 *
12 * 1. logging/setLevel - Sets the logging level for the server
13 * - Takes a logging level parameter (e.g., "debug", "info", "warning", "error")
14 * - Configures which severity of log messages the server should send
15 * - Does not affect internal server logging, only what's sent to the client
16 * - Server responds with an empty result on success
17 *
18 * The logging namespace helps clients control debugging information
19 * and monitor server activity by adjusting the amount of logging
20 * information provided by the server. After setting the level,
21 * clients may receive logging notifications matching that level.
22 *
23 * The server logs are sent as notifications/message events, providing
24 * real-time monitoring of server operations for debugging purposes.
25 */
26
27 #include "mcp.h"
28 #include "mcp-logging.h"
29
30 // Implementation of logging/setLevel (transport-agnostic)
31 static MCP_RETURN_CODE mcp_logging_method_setLevel(MCP_CLIENT *mcpc, struct json_object *params, MCP_REQUEST_ID id __maybe_unused) {
32 if (!mcpc)
33 return MCP_RC_ERROR;
34
35 // Extract level parameter
36 struct json_object *level_obj = NULL;
37 if (!json_object_object_get_ex(params, "level", &level_obj)) {
38 buffer_sprintf(mcpc->error, "Missing required parameter 'level'");
39 return MCP_RC_BAD_REQUEST;
40 }
41
42 if (!json_object_is_type(level_obj, json_type_string)) {
43 buffer_sprintf(mcpc->error, "Parameter 'level' must be a string");
44 return MCP_RC_BAD_REQUEST;
45 }
46
47 const char *level = json_object_get_string(level_obj);
48
49 // Validate log level
50 if (!level || !*level) {
51 buffer_sprintf(mcpc->error, "Log level cannot be empty");
52 return MCP_RC_BAD_REQUEST;
53 }
54
55 // Parse the log level using the enum string mapping
56 MCP_LOGGING_LEVEL parsed_level = MCP_LOGGING_LEVEL_2id(level);
57 if (parsed_level == MCP_LOGGING_LEVEL_UNKNOWN) {
58 buffer_sprintf(mcpc->error, "Invalid log level: '%s'. Valid values are: debug, info, notice, warning, error, critical, alert, emergency", level);
59 return MCP_RC_BAD_REQUEST;
60 }
61
62 // Store the parsed log level in the client context
63 mcpc->logging_level = parsed_level;
64
65 // Log that we received this request and set the level
66 netdata_log_info("MCP client %s logging level set to: %s", string2str(mcpc->client_name), MCP_LOGGING_LEVEL_2str(parsed_level));
67
68 // Initialize success' response with an empty result object
69 mcp_init_success_result(mcpc, id);
70 buffer_json_finalize(mcpc->result);
71
72 return MCP_RC_OK;
73 }
74
75 // Logging namespace method dispatcher (transport-agnostic)
76 MCP_RETURN_CODE mcp_logging_route(MCP_CLIENT *mcpc, const char *method, struct json_object *params, MCP_REQUEST_ID id) {
77 if (!mcpc || !method) return MCP_RC_INTERNAL_ERROR;
78
79 netdata_log_debug(D_MCP, "MCP logging method: %s", method);
80
81 MCP_RETURN_CODE rc;
82
83 if (strcmp(method, "setLevel") == 0) {
84 rc = mcp_logging_method_setLevel(mcpc, params, id);
85 }
86 else {
87 // Method not found in logging namespace
88 buffer_sprintf(mcpc->error, "Method 'logging/%s' not supported. The MCP specification only defines 'setLevel' method.", method);
89 rc = MCP_RC_NOT_IMPLEMENTED;
90 }
91
92 return rc;
93 }