@@ -33,6 +33,14 @@ class AlertmanagerConfig:
3333 password = os .environ .get ("ALERTMANAGER_PASSWORD" , "" ),
3434)
3535
36+ # Pagination defaults and limits (configurable via environment variables)
37+ DEFAULT_SILENCE_PAGE = int (os .environ .get ("ALERTMANAGER_DEFAULT_SILENCE_PAGE" , "10" ))
38+ MAX_SILENCE_PAGE = int (os .environ .get ("ALERTMANAGER_MAX_SILENCE_PAGE" , "50" ))
39+ DEFAULT_ALERT_PAGE = int (os .environ .get ("ALERTMANAGER_DEFAULT_ALERT_PAGE" , "10" ))
40+ MAX_ALERT_PAGE = int (os .environ .get ("ALERTMANAGER_MAX_ALERT_PAGE" , "25" ))
41+ DEFAULT_ALERT_GROUP_PAGE = int (os .environ .get ("ALERTMANAGER_DEFAULT_ALERT_GROUP_PAGE" , "3" ))
42+ MAX_ALERT_GROUP_PAGE = int (os .environ .get ("ALERTMANAGER_MAX_ALERT_GROUP_PAGE" , "5" ))
43+
3644
3745def make_request (method = "GET" , route = "/" , ** kwargs ):
3846 """Make HTTP request and return a requests.Response object.
@@ -67,6 +75,79 @@ def make_request(method="GET", route="/", **kwargs):
6775 return response .json ()
6876
6977
78+ def validate_pagination_params (count : int , offset : int , max_count : int ) -> tuple [int , int , Optional [str ]]:
79+ """Validate and normalize pagination parameters.
80+
81+ Parameters
82+ ----------
83+ count : int
84+ Requested number of items per page
85+ offset : int
86+ Requested offset for pagination
87+ max_count : int
88+ Maximum allowed count value
89+
90+ Returns
91+ -------
92+ tuple[int, int, Optional[str]]
93+ A tuple of (normalized_count, normalized_offset, error_message).
94+ If error_message is not None, the parameters are invalid and should
95+ return an error to the caller.
96+ """
97+ error = None
98+
99+ # Validate count parameter
100+ if count < 1 :
101+ error = f"Count parameter ({ count } ) must be at least 1."
102+ elif count > max_count :
103+ error = (
104+ f"Count parameter ({ count } ) exceeds maximum allowed value ({ max_count } ). "
105+ f"Please use count <= { max_count } and paginate through results using the offset parameter."
106+ )
107+
108+ # Validate offset parameter
109+ if offset < 0 :
110+ error = f"Offset parameter ({ offset } ) must be non-negative (>= 0)."
111+
112+ return count , offset , error
113+
114+
115+ def paginate_results (items : List [Any ], count : int , offset : int ) -> Dict [str , Any ]:
116+ """Apply pagination to a list of items and generate pagination metadata.
117+
118+ Parameters
119+ ----------
120+ items : List[Any]
121+ The full list of items to paginate
122+ count : int
123+ Number of items to return per page (must be >= 1)
124+ offset : int
125+ Number of items to skip (must be >= 0)
126+
127+ Returns
128+ -------
129+ Dict[str, Any]
130+ A dictionary containing:
131+ - data: List of items for the current page
132+ - pagination: Metadata including total, offset, count, requested_count, and has_more
133+ """
134+ total = len (items )
135+ end_index = offset + count
136+ paginated_items = items [offset :end_index ]
137+ has_more = end_index < total
138+
139+ return {
140+ "data" : paginated_items ,
141+ "pagination" : {
142+ "total" : total ,
143+ "offset" : offset ,
144+ "count" : len (paginated_items ),
145+ "requested_count" : count ,
146+ "has_more" : has_more
147+ }
148+ }
149+
150+
70151@mcp .tool (description = "Get current status of an Alertmanager instance and its cluster" )
71152async def get_status ():
72153 """Get current status of an Alertmanager instance and its cluster
@@ -93,24 +174,44 @@ async def get_receivers():
93174
94175
95176@mcp .tool (description = "Get list of all silences" )
96- async def get_silences (filter : Optional [str ] = None ):
177+ async def get_silences (filter : Optional [str ] = None ,
178+ count : int = DEFAULT_SILENCE_PAGE ,
179+ offset : int = 0 ):
97180 """Get list of all silences
98181
99182 Parameters
100183 ----------
101184 filter
102185 Filtering query (e.g. alertname=~'.*CPU.*')"),
186+ count
187+ Number of silences to return per page (default: 10, max: 50).
188+ offset
189+ Number of silences to skip before returning results (default: 0).
190+ To paginate through all results, make multiple calls with increasing
191+ offset values (e.g., offset=0, offset=10, offset=20, etc.).
103192
104193 Returns
105194 -------
106- list:
107- Return a list of Silence objects from Alertmanager instance.
195+ dict
196+ A dictionary containing:
197+ - data: List of Silence objects for the current page
198+ - pagination: Metadata about pagination (total, offset, count, has_more)
199+ Use the 'has_more' flag to determine if additional pages are available.
108200 """
201+ # Validate pagination parameters
202+ count , offset , error = validate_pagination_params (count , offset , MAX_SILENCE_PAGE )
203+ if error :
204+ return {"error" : error }
109205
110206 params = None
111207 if filter :
112208 params = {"filter" : filter }
113- return make_request (method = "GET" , route = "/api/v2/silences" , params = params )
209+
210+ # Get all silences from the API
211+ all_silences = make_request (method = "GET" , route = "/api/v2/silences" , params = params )
212+
213+ # Apply pagination and return results
214+ return paginate_results (all_silences , count , offset )
114215
115216
116217@mcp .tool (description = "Post a new silence or update an existing one" )
@@ -176,7 +277,9 @@ async def delete_silence(silence_id: str):
176277async def get_alerts (filter : Optional [str ] = None ,
177278 silenced : Optional [bool ] = None ,
178279 inhibited : Optional [bool ] = None ,
179- active : Optional [bool ] = None ):
280+ active : Optional [bool ] = None ,
281+ count : int = DEFAULT_ALERT_PAGE ,
282+ offset : int = 0 ):
180283 """Get a list of alerts currently in Alertmanager.
181284
182285 Params
@@ -189,12 +292,26 @@ async def get_alerts(filter: Optional[str] = None,
189292 If true, include inhibited alerts.
190293 active
191294 If true, include active alerts.
295+ count
296+ Number of alerts to return per page (default: 10, max: 25).
297+ offset
298+ Number of alerts to skip before returning results (default: 0).
299+ To paginate through all results, make multiple calls with increasing
300+ offset values (e.g., offset=0, offset=10, offset=20, etc.).
192301
193302 Returns
194303 -------
195- list
196- Return a list of Alert objects from Alertmanager instance.
304+ dict
305+ A dictionary containing:
306+ - data: List of Alert objects for the current page
307+ - pagination: Metadata about pagination (total, offset, count, has_more)
308+ Use the 'has_more' flag to determine if additional pages are available.
197309 """
310+ # Validate pagination parameters
311+ count , offset , error = validate_pagination_params (count , offset , MAX_ALERT_PAGE )
312+ if error :
313+ return {"error" : error }
314+
198315 params = {"active" : True }
199316 if filter :
200317 params = {"filter" : filter }
@@ -204,7 +321,12 @@ async def get_alerts(filter: Optional[str] = None,
204321 params ["inhibited" ] = inhibited
205322 if active is not None :
206323 params ["active" ] = active
207- return make_request (method = "GET" , route = "/api/v2/alerts" , params = params )
324+
325+ # Get all alerts from the API
326+ all_alerts = make_request (method = "GET" , route = "/api/v2/alerts" , params = params )
327+
328+ # Apply pagination and return results
329+ return paginate_results (all_alerts , count , offset )
208330
209331
210332@mcp .tool (description = "Create new alerts" )
@@ -234,7 +356,9 @@ async def post_alerts(alerts: List[Dict]):
234356@mcp .tool (description = "Get a list of alert groups" )
235357async def get_alert_groups (silenced : Optional [bool ] = None ,
236358 inhibited : Optional [bool ] = None ,
237- active : Optional [bool ] = None ):
359+ active : Optional [bool ] = None ,
360+ count : int = DEFAULT_ALERT_GROUP_PAGE ,
361+ offset : int = 0 ):
238362 """Get a list of alert groups
239363
240364 Params
@@ -245,21 +369,41 @@ async def get_alert_groups(silenced: Optional[bool] = None,
245369 If true, include inhibited alerts.
246370 active
247371 If true, include active alerts.
372+ count
373+ Number of alert groups to return per page (default: 3, max: 5).
374+ Alert groups can be large as they contain all alerts within the group.
375+ offset
376+ Number of alert groups to skip before returning results (default: 0).
377+ To paginate through all results, make multiple calls with increasing
378+ offset values (e.g., offset=0, offset=3, offset=6, etc.).
248379
249380 Returns
250381 -------
251- list
252- Return a list of AlertGroup objects from Alertmanager instance.
382+ dict
383+ A dictionary containing:
384+ - data: List of AlertGroup objects for the current page
385+ - pagination: Metadata about pagination (total, offset, count, has_more)
386+ Use the 'has_more' flag to determine if additional pages are available.
253387 """
388+ # Validate pagination parameters
389+ count , offset , error = validate_pagination_params (count , offset , MAX_ALERT_GROUP_PAGE )
390+ if error :
391+ return {"error" : error }
392+
254393 params = {"active" : True }
255394 if silenced is not None :
256395 params ["silenced" ] = silenced
257396 if inhibited is not None :
258397 params ["inhibited" ] = inhibited
259398 if active is not None :
260399 params ["active" ] = active
261- return make_request (method = "GET" , route = "/api/v2/alerts/groups" ,
262- params = params )
400+
401+ # Get all alert groups from the API
402+ all_groups = make_request (method = "GET" , route = "/api/v2/alerts/groups" ,
403+ params = params )
404+
405+ # Apply pagination and return results
406+ return paginate_results (all_groups , count , offset )
263407
264408
265409def setup_environment ():
0 commit comments