mcp-instana 0.2.1__py3-none-any.whl → 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. {mcp_instana-0.2.1.dist-info → mcp_instana-0.3.1.dist-info}/METADATA +69 -40
  2. {mcp_instana-0.2.1.dist-info → mcp_instana-0.3.1.dist-info}/RECORD +29 -29
  3. src/application/application_alert_config.py +45 -12
  4. src/application/application_analyze.py +28 -6
  5. src/application/application_catalog.py +11 -2
  6. src/application/application_global_alert_config.py +60 -21
  7. src/application/application_metrics.py +20 -4
  8. src/application/application_resources.py +20 -4
  9. src/application/application_settings.py +111 -35
  10. src/application/application_topology.py +22 -14
  11. src/automation/action_catalog.py +165 -188
  12. src/automation/action_history.py +21 -6
  13. src/core/server.py +7 -1
  14. src/core/utils.py +42 -5
  15. src/event/events_tools.py +30 -7
  16. src/infrastructure/infrastructure_analyze.py +18 -4
  17. src/infrastructure/infrastructure_catalog.py +72 -16
  18. src/infrastructure/infrastructure_metrics.py +5 -1
  19. src/infrastructure/infrastructure_resources.py +30 -11
  20. src/infrastructure/infrastructure_topology.py +10 -2
  21. src/log/log_alert_configuration.py +106 -31
  22. src/settings/custom_dashboard_tools.py +30 -7
  23. src/website/website_analyze.py +10 -2
  24. src/website/website_catalog.py +14 -3
  25. src/website/website_configuration.py +54 -13
  26. src/website/website_metrics.py +10 -2
  27. {mcp_instana-0.2.1.dist-info → mcp_instana-0.3.1.dist-info}/WHEEL +0 -0
  28. {mcp_instana-0.2.1.dist-info → mcp_instana-0.3.1.dist-info}/entry_points.txt +0 -0
  29. {mcp_instana-0.2.1.dist-info → mcp_instana-0.3.1.dist-info}/licenses/LICENSE.md +0 -0
@@ -22,7 +22,9 @@ except ImportError:
22
22
  logger.error("Failed to import Instana client modules", exc_info=True)
23
23
  raise
24
24
 
25
- from src.core.utils import BaseInstanaClient, register_as_tool
25
+ from mcp.types import ToolAnnotations
26
+
27
+ from src.core.utils import BaseInstanaClient, register_as_tool, with_header_auth
26
28
 
27
29
 
28
30
  class LogAlertConfigurationMCPTools(BaseInstanaClient):
@@ -51,8 +53,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
51
53
  logger.error(f"Error initializing LogAlertConfigurationApi: {e}", exc_info=True)
52
54
  raise
53
55
 
54
- @register_as_tool
55
- async def create_log_alert_config(self, config: Dict[str, Any], ctx=None) -> Dict[str, Any]:
56
+ @register_as_tool(
57
+ title="Create Log Alert Config",
58
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
59
+ )
60
+ @with_header_auth(LogAlertConfigurationApi)
61
+ async def create_log_alert_config(self, config: Dict[str, Any], ctx=None, api_client=None) -> Dict[str, Any]:
56
62
  """
57
63
  Create a new log alert configuration.
58
64
 
@@ -81,8 +87,9 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
81
87
 
82
88
  try:
83
89
  # Call the API
84
- result = self.log_alert_api.create_log_alert_config(log_alert_config=log_alert_config)
90
+ result = api_client.create_log_alert_config(log_alert_config=log_alert_config)
85
91
  logger.debug(f"Result from create_log_alert_config: {result}")
92
+
86
93
  return self._convert_to_dict(result)
87
94
  except Exception as e:
88
95
  logger.error(f"Error calling create_log_alert_config API: {e}", exc_info=True)
@@ -91,8 +98,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
91
98
  logger.error(f"Error in create_log_alert_config: {e}", exc_info=True)
92
99
  return {"error": f"Failed to create log alert configuration: {e!s}"}
93
100
 
94
- @register_as_tool
95
- async def delete_log_alert_config(self, id: str, ctx=None) -> Dict[str, Any]:
101
+ @register_as_tool(
102
+ title="Delete Log Alert Config",
103
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=True)
104
+ )
105
+ @with_header_auth(LogAlertConfigurationApi)
106
+ async def delete_log_alert_config(self, id: str, ctx=None, api_client=None) -> Dict[str, Any]:
96
107
  """
97
108
  Delete a log alert configuration.
98
109
 
@@ -107,7 +118,7 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
107
118
  logger.debug(f"delete_log_alert_config called with id={id}")
108
119
 
109
120
  try:
110
- self.log_alert_api.delete_log_alert_config(id=id)
121
+ api_client.delete_log_alert_config(id=id)
111
122
  logger.debug(f"Successfully deleted log alert configuration with ID {id}")
112
123
  return {"success": True, "message": f"Log alert configuration with ID {id} deleted successfully"}
113
124
  except Exception as e:
@@ -117,8 +128,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
117
128
  logger.error(f"Error in delete_log_alert_config: {e}", exc_info=True)
118
129
  return {"error": f"Failed to delete log alert configuration: {e!s}"}
119
130
 
120
- @register_as_tool
121
- async def disable_log_alert_config(self, id: str, ctx=None) -> Dict[str, Any]:
131
+ @register_as_tool(
132
+ title="Disable Log Alert Config",
133
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
134
+ )
135
+ @with_header_auth(LogAlertConfigurationApi)
136
+ async def disable_log_alert_config(self, id: str, ctx=None, api_client=None) -> Dict[str, Any]:
122
137
  """
123
138
  Disable a log alert configuration.
124
139
 
@@ -133,7 +148,7 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
133
148
  logger.debug(f"disable_log_alert_config called with id={id}")
134
149
 
135
150
  try:
136
- self.log_alert_api.disable_log_alert_config(id=id)
151
+ api_client.disable_log_alert_config(id=id)
137
152
  logger.debug(f"Successfully disabled log alert configuration with ID {id}")
138
153
  return {"success": True, "message": f"Log alert configuration with ID {id} disabled successfully"}
139
154
  except Exception as e:
@@ -143,8 +158,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
143
158
  logger.error(f"Error in disable_log_alert_config: {e}", exc_info=True)
144
159
  return {"error": f"Failed to disable log alert configuration: {e!s}"}
145
160
 
146
- @register_as_tool
147
- async def enable_log_alert_config(self, id: str, ctx=None) -> Dict[str, Any]:
161
+ @register_as_tool(
162
+ title="Enable Log Alert Config",
163
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
164
+ )
165
+ @with_header_auth(LogAlertConfigurationApi)
166
+ async def enable_log_alert_config(self, id: str, ctx=None, api_client=None) -> Dict[str, Any]:
148
167
  """
149
168
  Enable a log alert configuration.
150
169
 
@@ -159,7 +178,7 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
159
178
  logger.debug(f"enable_log_alert_config called with id={id}")
160
179
 
161
180
  try:
162
- self.log_alert_api.enable_log_alert_config(id=id)
181
+ api_client.enable_log_alert_config(id=id)
163
182
  logger.debug(f"Successfully enabled log alert configuration with ID {id}")
164
183
  return {"success": True, "message": f"Log alert configuration with ID {id} enabled successfully"}
165
184
  except Exception as e:
@@ -169,8 +188,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
169
188
  logger.error(f"Error in enable_log_alert_config: {e}", exc_info=True)
170
189
  return {"error": f"Failed to enable log alert configuration: {e!s}"}
171
190
 
172
- @register_as_tool
173
- async def find_active_log_alert_configs(self, alert_ids: Optional[List[str]] = None, ctx=None) -> Dict[str, Any]:
191
+ @register_as_tool(
192
+ title="Find Active Log Alert Configs",
193
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
194
+ )
195
+ @with_header_auth(LogAlertConfigurationApi)
196
+ async def find_active_log_alert_configs(self, alert_ids: Optional[List[str]] = None, ctx=None, api_client=None) -> Dict[str, Any]:
174
197
  """
175
198
  Get all active log alert configurations.
176
199
 
@@ -185,9 +208,21 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
185
208
  logger.debug(f"find_active_log_alert_configs called with alert_ids={alert_ids}")
186
209
 
187
210
  try:
188
- result = self.log_alert_api.find_active_log_alert_configs(alert_ids=alert_ids)
211
+ # Call the API with raw JSON response to avoid Pydantic validation issues
212
+ result = api_client.find_active_log_alert_configs_without_preload_content(alert_ids=alert_ids)
189
213
  logger.debug(f"Result from find_active_log_alert_configs: {result}")
190
- return {"configs": [self._convert_to_dict(config) for config in result]}
214
+
215
+ # Parse the JSON response manually
216
+ import json
217
+ try:
218
+ response_text = result.data.decode('utf-8')
219
+ result_list = json.loads(response_text)
220
+ logger.debug("Successfully retrieved active log alert configurations")
221
+ return {"configs": result_list}
222
+ except (json.JSONDecodeError, AttributeError) as json_err:
223
+ error_message = f"Failed to parse JSON response: {json_err}"
224
+ logger.error(error_message)
225
+ return {"error": error_message}
191
226
  except Exception as e:
192
227
  logger.error(f"Error calling find_active_log_alert_configs API: {e}", exc_info=True)
193
228
  return {"error": f"Failed to find active log alert configurations: {e!s}"}
@@ -195,8 +230,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
195
230
  logger.error(f"Error in find_active_log_alert_configs: {e}", exc_info=True)
196
231
  return {"error": f"Failed to find active log alert configurations: {e!s}"}
197
232
 
198
- @register_as_tool
199
- async def find_log_alert_config(self, id: str, valid_on: Optional[int] = None, ctx=None) -> Dict[str, Any]:
233
+ @register_as_tool(
234
+ title="Find Log Alert Config",
235
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
236
+ )
237
+ @with_header_auth(LogAlertConfigurationApi)
238
+ async def find_log_alert_config(self, id: str, valid_on: Optional[int] = None, ctx=None, api_client=None) -> Dict[str, Any]:
200
239
  """
201
240
  Get a specific log alert configuration by ID.
202
241
 
@@ -212,9 +251,21 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
212
251
  logger.debug(f"find_log_alert_config called with id={id}, valid_on={valid_on}")
213
252
 
214
253
  try:
215
- result = self.log_alert_api.find_log_alert_config(id=id, valid_on=valid_on)
254
+ # Call the API with raw JSON response to avoid Pydantic validation issues
255
+ result = api_client.find_log_alert_config_without_preload_content(id=id, valid_on=valid_on)
216
256
  logger.debug(f"Result from find_log_alert_config: {result}")
217
- return self._convert_to_dict(result)
257
+
258
+ # Parse the JSON response manually
259
+ import json
260
+ try:
261
+ response_text = result.data.decode('utf-8')
262
+ result_dict = json.loads(response_text)
263
+ logger.debug("Successfully retrieved log alert configuration")
264
+ return result_dict
265
+ except (json.JSONDecodeError, AttributeError) as json_err:
266
+ error_message = f"Failed to parse JSON response: {json_err}"
267
+ logger.error(error_message)
268
+ return {"error": error_message}
218
269
  except Exception as e:
219
270
  logger.error(f"Error calling find_log_alert_config API: {e}", exc_info=True)
220
271
  return {"error": f"Failed to find log alert configuration: {e!s}"}
@@ -222,8 +273,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
222
273
  logger.error(f"Error in find_log_alert_config: {e}", exc_info=True)
223
274
  return {"error": f"Failed to find log alert configuration: {e!s}"}
224
275
 
225
- @register_as_tool
226
- async def find_log_alert_config_versions(self, id: str, ctx=None) -> Dict[str, Any]:
276
+ @register_as_tool(
277
+ title="Find Log Alert Config Versions",
278
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
279
+ )
280
+ @with_header_auth(LogAlertConfigurationApi)
281
+ async def find_log_alert_config_versions(self, id: str, ctx=None, api_client=None) -> Dict[str, Any]:
227
282
  """
228
283
  Get all versions of a log alert configuration.
229
284
 
@@ -238,9 +293,21 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
238
293
  logger.debug(f"find_log_alert_config_versions called with id={id}")
239
294
 
240
295
  try:
241
- result = self.log_alert_api.find_log_alert_config_versions(id=id)
296
+ # Call the API with raw JSON response to avoid Pydantic validation issues
297
+ result = api_client.find_log_alert_config_versions_without_preload_content(id=id)
242
298
  logger.debug(f"Result from find_log_alert_config_versions: {result}")
243
- return {"versions": [self._convert_to_dict(version) for version in result]}
299
+
300
+ # Parse the JSON response manually
301
+ import json
302
+ try:
303
+ response_text = result.data.decode('utf-8')
304
+ result_list = json.loads(response_text)
305
+ logger.debug("Successfully retrieved log alert configuration versions")
306
+ return {"versions": result_list}
307
+ except (json.JSONDecodeError, AttributeError) as json_err:
308
+ error_message = f"Failed to parse JSON response: {json_err}"
309
+ logger.error(error_message)
310
+ return {"error": error_message}
244
311
  except Exception as e:
245
312
  logger.error(f"Error calling find_log_alert_config_versions API: {e}", exc_info=True)
246
313
  return {"error": f"Failed to find log alert configuration versions: {e!s}"}
@@ -248,8 +315,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
248
315
  logger.error(f"Error in find_log_alert_config_versions: {e}", exc_info=True)
249
316
  return {"error": f"Failed to find log alert configuration versions: {e!s}"}
250
317
 
251
- @register_as_tool
252
- async def restore_log_alert_config(self, id: str, created: int, ctx=None) -> Dict[str, Any]:
318
+ @register_as_tool(
319
+ title="Restore Log Alert Config",
320
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
321
+ )
322
+ @with_header_auth(LogAlertConfigurationApi)
323
+ async def restore_log_alert_config(self, id: str, created: int, ctx=None, api_client=None) -> Dict[str, Any]:
253
324
  """
254
325
  Restore a log alert configuration to a previous version.
255
326
 
@@ -265,7 +336,7 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
265
336
  logger.debug(f"restore_log_alert_config called with id={id}, created={created}")
266
337
 
267
338
  try:
268
- self.log_alert_api.restore_log_alert_config(id=id, created=created)
339
+ api_client.restore_log_alert_config(id=id, created=created)
269
340
  logger.debug(f"Successfully restored log alert configuration with ID {id}")
270
341
  return {
271
342
  "success": True,
@@ -278,8 +349,12 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
278
349
  logger.error(f"Error in restore_log_alert_config: {e}", exc_info=True)
279
350
  return {"error": f"Failed to restore log alert configuration: {e!s}"}
280
351
 
281
- @register_as_tool
282
- async def update_log_alert_config(self, id: str, config: Dict[str, Any], ctx=None) -> Dict[str, Any]:
352
+ @register_as_tool(
353
+ title="Update Log Alert Config",
354
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
355
+ )
356
+ @with_header_auth(LogAlertConfigurationApi)
357
+ async def update_log_alert_config(self, id: str, config: Dict[str, Any], ctx=None, api_client=None) -> Dict[str, Any]:
283
358
  """
284
359
  Update a log alert configuration.
285
360
 
@@ -303,7 +378,7 @@ class LogAlertConfigurationMCPTools(BaseInstanaClient):
303
378
 
304
379
  try:
305
380
  # Call the API
306
- result = self.log_alert_api.update_log_alert_config(id=id, log_alert_config=log_alert_config)
381
+ result = api_client.update_log_alert_config(id=id, log_alert_config=log_alert_config)
307
382
  logger.debug(f"Result from update_log_alert_config: {result}")
308
383
  return self._convert_to_dict(result)
309
384
  except Exception as e:
@@ -8,6 +8,8 @@ import json
8
8
  import logging
9
9
  from typing import Any, Dict, List, Optional
10
10
 
11
+ from mcp.types import ToolAnnotations
12
+
11
13
  from src.core.utils import (
12
14
  BaseInstanaClient,
13
15
  register_as_tool,
@@ -34,7 +36,10 @@ class CustomDashboardMCPTools(BaseInstanaClient):
34
36
  """Initialize the Custom Dashboard MCP tools client."""
35
37
  super().__init__(read_token=read_token, base_url=base_url)
36
38
 
37
- @register_as_tool
39
+ @register_as_tool(
40
+ title="Get Custom Dashboards",
41
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
42
+ )
38
43
  @with_header_auth(CustomDashboardsApi)
39
44
  async def get_custom_dashboards(self,
40
45
  ctx=None, api_client=None) -> Dict[str, Any]:
@@ -89,7 +94,10 @@ class CustomDashboardMCPTools(BaseInstanaClient):
89
94
  logger.error(f"Error in get_custom_dashboards: {e}", exc_info=True)
90
95
  return {"error": f"Failed to get custom dashboards: {e!s}"}
91
96
 
92
- @register_as_tool
97
+ @register_as_tool(
98
+ title="Get Custom Dashboard",
99
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
100
+ )
93
101
  @with_header_auth(CustomDashboardsApi)
94
102
  async def get_custom_dashboard(self,
95
103
  dashboard_id: str,
@@ -137,7 +145,10 @@ class CustomDashboardMCPTools(BaseInstanaClient):
137
145
  logger.error(f"Error in get_custom_dashboard: {e}", exc_info=True)
138
146
  return {"error": f"Failed to get custom dashboard: {e!s}"}
139
147
 
140
- @register_as_tool
148
+ @register_as_tool(
149
+ title="Add Custom Dashboard",
150
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
151
+ )
141
152
  @with_header_auth(CustomDashboardsApi)
142
153
  async def add_custom_dashboard(self,
143
154
  custom_dashboard: Dict[str, Any],
@@ -192,7 +203,10 @@ class CustomDashboardMCPTools(BaseInstanaClient):
192
203
  logger.error(f"Error in add_custom_dashboard: {e}", exc_info=True)
193
204
  return {"error": f"Failed to add custom dashboard: {e!s}"}
194
205
 
195
- @register_as_tool
206
+ @register_as_tool(
207
+ title="Update Custom Dashboard",
208
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
209
+ )
196
210
  @with_header_auth(CustomDashboardsApi)
197
211
  async def update_custom_dashboard(self,
198
212
  dashboard_id: str,
@@ -251,7 +265,10 @@ class CustomDashboardMCPTools(BaseInstanaClient):
251
265
  logger.error(f"Error in update_custom_dashboard: {e}", exc_info=True)
252
266
  return {"error": f"Failed to update custom dashboard: {e!s}"}
253
267
 
254
- @register_as_tool
268
+ @register_as_tool(
269
+ title="Delete Custom Dashboard",
270
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=True)
271
+ )
255
272
  @with_header_auth(CustomDashboardsApi)
256
273
  async def delete_custom_dashboard(self,
257
274
  dashboard_id: str,
@@ -298,7 +315,10 @@ class CustomDashboardMCPTools(BaseInstanaClient):
298
315
  logger.error(f"Error in delete_custom_dashboard: {e}", exc_info=True)
299
316
  return {"error": f"Failed to delete custom dashboard: {e!s}"}
300
317
 
301
- @register_as_tool
318
+ @register_as_tool(
319
+ title="Get Shareable Users",
320
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
321
+ )
302
322
  @with_header_auth(CustomDashboardsApi)
303
323
  async def get_shareable_users(self,
304
324
  dashboard_id: str,
@@ -357,7 +377,10 @@ class CustomDashboardMCPTools(BaseInstanaClient):
357
377
  logger.error(f"Error in get_shareable_users: {e}", exc_info=True)
358
378
  return {"error": f"Failed to get shareable users: {e!s}"}
359
379
 
360
- @register_as_tool
380
+ @register_as_tool(
381
+ title="Get Shareable API Tokens",
382
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
383
+ )
361
384
  @with_header_auth(CustomDashboardsApi)
362
385
  async def get_shareable_api_tokens(self,
363
386
  dashboard_id: str,
@@ -34,6 +34,8 @@ except ImportError as e:
34
34
  logger.error(f"Error importing Instana SDK: {e}", exc_info=True)
35
35
  raise
36
36
 
37
+ from mcp.types import ToolAnnotations
38
+
37
39
  from src.core.utils import BaseInstanaClient, register_as_tool, with_header_auth
38
40
 
39
41
  # Configure logger for this module
@@ -47,7 +49,10 @@ class WebsiteAnalyzeMCPTools(BaseInstanaClient):
47
49
  """Initialize the Website Analyze MCP tools client."""
48
50
  super().__init__(read_token=read_token, base_url=base_url)
49
51
 
50
- @register_as_tool
52
+ @register_as_tool(
53
+ title="Get Website Beacon Groups",
54
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
55
+ )
51
56
  @with_header_auth(WebsiteAnalyzeApi)
52
57
  async def get_website_beacon_groups(self,
53
58
  payload: Optional[Union[Dict[str, Any], str]] = None,
@@ -263,7 +268,10 @@ class WebsiteAnalyzeMCPTools(BaseInstanaClient):
263
268
  return {"error": f"Failed to get website beacon groups: {e!s}"}
264
269
 
265
270
 
266
- @register_as_tool
271
+ @register_as_tool(
272
+ title="Get Website Beacons",
273
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
274
+ )
267
275
  @with_header_auth(WebsiteAnalyzeApi)
268
276
  async def get_website_beacons(self,
269
277
  payload: Optional[Union[Dict[str, Any], str]] = None,
@@ -16,6 +16,8 @@ except ImportError as e:
16
16
  logger.error(f"Error importing Instana SDK: {e}", exc_info=True)
17
17
  raise
18
18
 
19
+ from mcp.types import ToolAnnotations
20
+
19
21
  from src.core.utils import BaseInstanaClient, register_as_tool, with_header_auth
20
22
 
21
23
  # Configure logger for this module
@@ -28,7 +30,10 @@ class WebsiteCatalogMCPTools(BaseInstanaClient):
28
30
  """Initialize the Website Catalog MCP tools client."""
29
31
  super().__init__(read_token=read_token, base_url=base_url)
30
32
 
31
- @register_as_tool
33
+ @register_as_tool(
34
+ title="Get Website Catalog Metrics",
35
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
36
+ )
32
37
  @with_header_auth(WebsiteCatalogApi)
33
38
  async def get_website_catalog_metrics(self, ctx=None, api_client=None) -> Dict[str, Any]:
34
39
  """
@@ -76,7 +81,10 @@ class WebsiteCatalogMCPTools(BaseInstanaClient):
76
81
  logger.error(f"Error in get_website_catalog_metrics: {e}", exc_info=True)
77
82
  return {"error": f"Failed to get website catalog metrics: {e!s}"}
78
83
 
79
- @register_as_tool
84
+ @register_as_tool(
85
+ title="Get Website Catalog Tags",
86
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
87
+ )
80
88
  @with_header_auth(WebsiteCatalogApi)
81
89
  async def get_website_catalog_tags(self, ctx=None, api_client=None) -> Dict[str, Any]:
82
90
  """
@@ -124,7 +132,10 @@ class WebsiteCatalogMCPTools(BaseInstanaClient):
124
132
  logger.error(f"Error in get_website_catalog_tags: {e}", exc_info=True)
125
133
  return {"error": f"Failed to get website catalog tags: {e!s}"}
126
134
 
127
- @register_as_tool
135
+ @register_as_tool(
136
+ title="Get Website Tag Catalog",
137
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
138
+ )
128
139
  @with_header_auth(WebsiteCatalogApi)
129
140
  async def get_website_tag_catalog(self,
130
141
  beacon_type: str,
@@ -16,6 +16,8 @@ except ImportError as e:
16
16
  logger.error(f"Error importing Instana SDK: {e}", exc_info=True)
17
17
  raise
18
18
 
19
+ from mcp.types import ToolAnnotations
20
+
19
21
  from src.core.utils import BaseInstanaClient, register_as_tool, with_header_auth
20
22
 
21
23
  # Configure logger for this module
@@ -28,7 +30,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
28
30
  """Initialize the Website Configuration MCP tools client."""
29
31
  super().__init__(read_token=read_token, base_url=base_url)
30
32
 
31
- @register_as_tool
33
+ @register_as_tool(
34
+ title="Get Websites",
35
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
36
+ )
32
37
  @with_header_auth(WebsiteConfigurationApi)
33
38
  async def get_websites(self, ctx=None, api_client=None) -> List[Dict[str, Any]]:
34
39
  """
@@ -61,7 +66,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
61
66
  logger.error(f"Error in get_websites: {e}", exc_info=True)
62
67
  return [{"error": f"Failed to get websites: {e!s}"}]
63
68
 
64
- @register_as_tool
69
+ @register_as_tool(
70
+ title="Get Website",
71
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
72
+ )
65
73
  @with_header_auth(WebsiteConfigurationApi)
66
74
  async def get_website(self, website_id: str, ctx=None, api_client=None) -> Dict[str, Any]:
67
75
  """
@@ -95,7 +103,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
95
103
  logger.error(f"Error in get_website: {e}", exc_info=True)
96
104
  return {"error": f"Failed to get website: {e!s}"}
97
105
 
98
- @register_as_tool
106
+ @register_as_tool(
107
+ title="Create Website",
108
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
109
+ )
99
110
  @with_header_auth(WebsiteConfigurationApi)
100
111
  async def create_website(self,
101
112
  name: str,
@@ -185,7 +196,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
185
196
  logger.error(f"Error in create_website: {e}")
186
197
  return {"error": f"Failed to create website: {e!s}"}
187
198
 
188
- @register_as_tool
199
+ @register_as_tool(
200
+ title="Delete Website",
201
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=True)
202
+ )
189
203
  @with_header_auth(WebsiteConfigurationApi)
190
204
  async def delete_website(self, website_id: str, ctx=None, api_client=None) -> Dict[str, Any]:
191
205
  """
@@ -212,7 +226,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
212
226
  logger.error(f"Error in delete_website: {e}", exc_info=True)
213
227
  return {"error": f"Failed to delete website: {e!s}"}
214
228
 
215
- @register_as_tool
229
+ @register_as_tool(
230
+ title="Rename Website",
231
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
232
+ )
216
233
  @with_header_auth(WebsiteConfigurationApi)
217
234
  async def rename_website(self,
218
235
  website_id: str,
@@ -255,7 +272,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
255
272
  logger.error(f"Error in rename_website: {e}", exc_info=True)
256
273
  return {"error": f"Failed to rename website: {e!s}"}
257
274
 
258
- @register_as_tool
275
+ @register_as_tool(
276
+ title="Get Website Geo Location Configuration",
277
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
278
+ )
259
279
  @with_header_auth(WebsiteConfigurationApi)
260
280
  async def get_website_geo_location_configuration(self,
261
281
  website_id: str,
@@ -292,7 +312,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
292
312
  logger.error(f"Error in get_website_geo_location_configuration: {e}", exc_info=True)
293
313
  return {"error": f"Failed to get website geo-location configuration: {e!s}"}
294
314
 
295
- @register_as_tool
315
+ @register_as_tool(
316
+ title="Update Website Geo Location Configuration",
317
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
318
+ )
296
319
  @with_header_auth(WebsiteConfigurationApi)
297
320
  async def update_website_geo_location_configuration(self,
298
321
  website_id: str,
@@ -408,7 +431,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
408
431
  logger.error(f"Error in update_website_geo_location_configuration: {e}")
409
432
  return {"error": f"Failed to update website geo-location configuration: {e!s}"}
410
433
 
411
- @register_as_tool
434
+ @register_as_tool(
435
+ title="Get Website IP Masking Configuration",
436
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
437
+ )
412
438
  @with_header_auth(WebsiteConfigurationApi)
413
439
  async def get_website_ip_masking_configuration(self, website_id: str, ctx=None, api_client=None) -> Dict[str, Any]:
414
440
  """
@@ -442,7 +468,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
442
468
  logger.error(f"Error in get_website_ip_masking_configuration: {e}", exc_info=True)
443
469
  return {"error": f"Failed to get website IP masking configuration: {e!s}"}
444
470
 
445
- @register_as_tool
471
+ @register_as_tool(
472
+ title="Update Website IP Masking Configuration",
473
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
474
+ )
446
475
  @with_header_auth(WebsiteConfigurationApi)
447
476
  async def update_website_ip_masking_configuration(self,
448
477
  website_id: str,
@@ -555,7 +584,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
555
584
  logger.error(f"Error in update_website_ip_masking_configuration: {e}")
556
585
  return {"error": f"Failed to update website ip-masking configuration: {e!s}"}
557
586
 
558
- @register_as_tool
587
+ @register_as_tool(
588
+ title="Get Website Geo Mapping Rules",
589
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
590
+ )
559
591
  @with_header_auth(WebsiteConfigurationApi)
560
592
  async def get_website_geo_mapping_rules(self, website_id: str, ctx=None, api_client=None) -> List[Dict[str, Any]]:
561
593
  """
@@ -619,7 +651,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
619
651
  logger.error(f"Error in get_website_geo_mapping_rules: {e}", exc_info=True)
620
652
  return [{"error": f"Failed to get website geo mapping rules: {e!s}"}]
621
653
 
622
- @register_as_tool
654
+ @register_as_tool(
655
+ title="Set Website Geo Mapping Rules",
656
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
657
+ )
623
658
  @with_header_auth(WebsiteConfigurationApi)
624
659
  async def set_website_geo_mapping_rules(self,
625
660
  website_id: str,
@@ -664,7 +699,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
664
699
  logger.error(f"Error in set_website_geo_mapping_rules: {e}", exc_info=True)
665
700
  return {"error": f"Failed to set website geo mapping rules: {e!s}"}
666
701
 
667
- @register_as_tool
702
+ @register_as_tool(
703
+ title="Upload Source Map File",
704
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
705
+ )
668
706
  @with_header_auth(WebsiteConfigurationApi)
669
707
  async def upload_source_map_file(self,
670
708
  website_id: str,
@@ -722,7 +760,10 @@ class WebsiteConfigurationMCPTools(BaseInstanaClient):
722
760
  logger.error(f"Error in upload_source_map_file: {e}")
723
761
  return {"error": f"Failed to upload source map file: {e!s}"}
724
762
 
725
- @register_as_tool
763
+ @register_as_tool(
764
+ title="Clear Source Map Upload Configuration",
765
+ annotations=ToolAnnotations(readOnlyHint=False, destructiveHint=False)
766
+ )
726
767
  @with_header_auth(WebsiteConfigurationApi)
727
768
  async def clear_source_map_upload_configuration(self,
728
769
  website_id: str,
@@ -18,6 +18,8 @@ except ImportError as e:
18
18
  logger.error(f"Error importing Instana SDK: {e}", exc_info=True)
19
19
  raise
20
20
 
21
+ from mcp.types import ToolAnnotations
22
+
21
23
  from src.core.utils import BaseInstanaClient, register_as_tool, with_header_auth
22
24
 
23
25
  # Configure logger for this module
@@ -30,7 +32,10 @@ class WebsiteMetricsMCPTools(BaseInstanaClient):
30
32
  """Initialize the Website Metrics MCP tools client."""
31
33
  super().__init__(read_token=read_token, base_url=base_url)
32
34
 
33
- @register_as_tool
35
+ @register_as_tool(
36
+ title="Get Website Page Load",
37
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
38
+ )
34
39
  @with_header_auth(WebsiteMetricsApi)
35
40
  async def get_website_page_load(self,
36
41
  page_id: str,
@@ -84,7 +89,10 @@ class WebsiteMetricsMCPTools(BaseInstanaClient):
84
89
  logger.error(f"Error in get_website_page_load: {e}", exc_info=True)
85
90
  return [{"error": f"Failed to get website page load: {e!s}"}]
86
91
 
87
- @register_as_tool
92
+ @register_as_tool(
93
+ title="Get Website Beacon Metrics V2",
94
+ annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False)
95
+ )
88
96
  @with_header_auth(WebsiteMetricsApi)
89
97
  async def get_website_beacon_metrics_v2(self,
90
98
  payload: Optional[Union[Dict[str, Any], str]] = None,