88import logging
99import os
1010import time
11- from datetime import datetime
12- from typing import Optional , Annotated , Any , Dict
11+ import datetime
12+ from typing import Optional , Annotated
1313from pydantic import Field
14- from sysdig_client import ApiException
1514from fastmcp .prompts .prompt import PromptMessage , TextContent
1615from fastmcp .exceptions import ToolError
17- from starlette .requests import Request
16+ from fastmcp .server .context import Context
17+ from sysdig_client import ApiException
1818from sysdig_client .api import SecureEventsApi
19- from utils .sysdig .old_sysdig_api import OldSysdigApi
20- from fastmcp .server .dependencies import get_http_request
19+ from utils .sysdig .legacy_sysdig_api import LegacySysdigApi
2120from utils .query_helpers import create_standard_response
22- from utils .sysdig .client_config import get_configuration
2321from utils .app_config import AppConfig
24- from utils .sysdig .api import initialize_api_client
2522
2623
2724class EventsFeedTools :
@@ -32,55 +29,23 @@ class EventsFeedTools:
3229
3330 def __init__ (self , app_config : AppConfig ):
3431 self .app_config = app_config
35- logging .basicConfig (format = "%(asctime)s-%(process)d-%(levelname)s- %(message)s" , level = self .app_config .log_level ())
3632 self .log = logging .getLogger (__name__ )
3733
38- def init_client (self , old_api : bool = False ) -> SecureEventsApi | OldSysdigApi :
39- """
40- Initializes the SecureEventsApi client from the request state.
41- If the request does not have the API client initialized, it will create a new instance
42- using the Sysdig Secure token and host from the environment variables.
43- Args:
44- old_api (bool): If True, initializes the OldSysdigApi client instead of SecureEventsApi.
45- Returns:
46- SecureEventsApi | OldSysdigApi: An instance of the SecureEventsApi or OldSysdigApi client.
47- """
48- secure_events_api : SecureEventsApi = None
49- old_sysdig_api : OldSysdigApi = None
50- transport = self .app_config .transport ()
51- if transport in ["streamable-http" , "sse" ]:
52- # Try to get the HTTP request
53- self .log .debug ("Attempting to get the HTTP request to initialize the Sysdig API client." )
54- request : Request = get_http_request ()
55- secure_events_api = request .state .api_instances ["secure_events" ]
56- old_sysdig_api = request .state .api_instances ["old_sysdig_api" ]
57- else :
58- # If running in STDIO mode, we need to initialize the API client from environment variables
59- self .log .debug ("Running in STDIO mode, initializing the Sysdig API client from environment variables." )
60- cfg = get_configuration ()
61- api_client = initialize_api_client (cfg )
62- secure_events_api = SecureEventsApi (api_client )
63- # Initialize the old Sysdig API client for process tree requests
64- old_cfg = get_configuration (old_api = True )
65- old_sysdig_api = initialize_api_client (old_cfg )
66- old_sysdig_api = OldSysdigApi (old_sysdig_api )
67-
68- if old_api :
69- return old_sysdig_api
70- return secure_events_api
71-
72- def tool_get_event_info (self , event_id : str ) -> dict :
34+ def tool_get_event_info (self , ctx : Context , event_id : str ) -> dict :
7335 """
7436 Retrieves detailed information for a specific security event.
7537
7638 Args:
39+ ctx (Context): Context to use.
7740 event_id (str): The unique identifier of the security event.
7841
7942 Returns:
8043 Event: The Event object containing detailed information about the specified event.
8144 """
8245 # Init of the sysdig client
83- secure_events_api = self .init_client ()
46+ api_instances : dict = ctx .get_state ("api_instances" )
47+ secure_events_api : SecureEventsApi = api_instances .get ("secure_events" )
48+
8449 try :
8550 # Get the HTTP request
8651 start_time = time .time ()
@@ -98,6 +63,7 @@ def tool_get_event_info(self, event_id: str) -> dict:
9863
9964 def tool_list_runtime_events (
10065 self ,
66+ ctx : Context ,
10167 cursor : Optional [str ] = None ,
10268 scope_hours : int = 1 ,
10369 limit : int = 50 ,
@@ -136,6 +102,7 @@ def tool_list_runtime_events(
136102 cluster name, or an optional filter expression.
137103
138104 Args:
105+ ctx (Context): Context to use.
139106 cursor (Optional[str]): Cursor for pagination.
140107 scope_hours (int): Number of hours back from now to include events. Defaults to 1.
141108 limit (int): Maximum number of events to return. Defaults to 50.
@@ -144,7 +111,9 @@ def tool_list_runtime_events(
144111 Returns:
145112 dict: A dictionary containing the results of the runtime events query, including pagination information.
146113 """
147- secure_events_api = self .init_client ()
114+ api_instances : dict = ctx .get_state ("api_instances" )
115+ secure_events_api : SecureEventsApi = api_instances .get ("secure_events" )
116+
148117 start_time = time .time ()
149118 # Compute time window
150119 now_ns = time .time_ns ()
@@ -176,7 +145,7 @@ def tool_list_runtime_events(
176145
177146 # A tool to retrieve all the process-tree information for a specific event.Add commentMore actions
178147
179- def tool_get_event_process_tree (self , event_id : str ) -> dict :
148+ def tool_get_event_process_tree (self , ctx : Context , event_id : str ) -> dict :
180149 """
181150 Retrieves the process tree for a specific security event.
182151 Not every event has a process tree, so this may return an empty tree.
@@ -191,12 +160,14 @@ def tool_get_event_process_tree(self, event_id: str) -> dict:
191160 ToolError: If there is an error constructing or processing the response.
192161 """
193162 try :
163+ api_instances : dict = ctx .get_state ("api_instances" )
164+ legacy_api_client : LegacySysdigApi = api_instances .get ("legacy_sysdig_api" )
165+
194166 start_time = time .time ()
195167 # Get process tree branches
196- old_api_client = self .init_client (old_api = True )
197- branches = old_api_client .request_process_tree_branches (event_id )
168+ branches = legacy_api_client .request_process_tree_branches (event_id )
198169 # Get process tree
199- tree = old_api_client .request_process_tree_trees (event_id )
170+ tree = legacy_api_client .request_process_tree_trees (event_id )
200171
201172 # Parse the response (tolerates empty bodies)
202173 branches_std = create_standard_response (results = branches , execution_time_ms = (time .time () - start_time ) * 1000 )
@@ -209,7 +180,7 @@ def tool_get_event_process_tree(self, event_id: str) -> dict:
209180 "tree" : tree_std .get ("results" , {}),
210181 "metadata" : {
211182 "execution_time_ms" : execution_time ,
212- "timestamp" : datetime .utcnow ( ).isoformat () + "Z" ,
183+ "timestamp" : datetime .datetime . now ( datetime . UTC ).isoformat (). replace ( "+00:00" , "Z" ) ,
213184 },
214185 }
215186
@@ -222,7 +193,7 @@ def tool_get_event_process_tree(self, event_id: str) -> dict:
222193 "tree" : {},
223194 "metadata" : {
224195 "execution_time_ms" : (time .time () - start_time ) * 1000 ,
225- "timestamp" : datetime .utcnow ( ).isoformat () + "Z" ,
196+ "timestamp" : datetime .datetime . now ( datetime . UTC ).isoformat (). replace ( "+00:00" , "Z" ) ,
226197 "note" : "Process tree not available for this event"
227198 },
228199 }
0 commit comments