mcp-instana 0.1.0__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.
- mcp_instana-0.1.0.dist-info/LICENSE +201 -0
- mcp_instana-0.1.0.dist-info/METADATA +649 -0
- mcp_instana-0.1.0.dist-info/RECORD +19 -0
- mcp_instana-0.1.0.dist-info/WHEEL +4 -0
- mcp_instana-0.1.0.dist-info/entry_points.txt +3 -0
- src/__init__.py +0 -0
- src/client/What is the sum of queue depth for all q +55 -0
- src/client/application_alert_config_mcp_tools.py +680 -0
- src/client/application_metrics_mcp_tools.py +377 -0
- src/client/application_resources_mcp_tools.py +391 -0
- src/client/events_mcp_tools.py +531 -0
- src/client/infrastructure_analyze_mcp_tools.py +634 -0
- src/client/infrastructure_catalog_mcp_tools.py +624 -0
- src/client/infrastructure_resources_mcp_tools.py +653 -0
- src/client/infrastructure_topology_mcp_tools.py +319 -0
- src/client/instana_client_base.py +93 -0
- src/client/log_alert_configuration_mcp_tools.py +316 -0
- src/client/show the top 5 services with the highest +28 -0
- src/mcp_server.py +343 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Application Metrics MCP Tools Module
|
|
3
|
+
|
|
4
|
+
This module provides application metrics-specific MCP tools for Instana monitoring.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import traceback
|
|
9
|
+
from typing import Dict, Any, Optional, List, Union
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
# Import the necessary classes from the SDK
|
|
13
|
+
try:
|
|
14
|
+
from instana_client.api.application_metrics_api import ApplicationMetricsApi
|
|
15
|
+
from instana_client.api_client import ApiClient
|
|
16
|
+
from instana_client.configuration import Configuration
|
|
17
|
+
from instana_client.models.get_application_metrics import GetApplicationMetrics
|
|
18
|
+
from instana_client.models.get_applications import GetApplications
|
|
19
|
+
from instana_client.models.get_endpoints import GetEndpoints
|
|
20
|
+
from instana_client.models.get_services import GetServices
|
|
21
|
+
except ImportError as e:
|
|
22
|
+
print(f"Error importing Instana SDK: {e}", file=sys.stderr)
|
|
23
|
+
traceback.print_exc(file=sys.stderr)
|
|
24
|
+
raise
|
|
25
|
+
|
|
26
|
+
from .instana_client_base import BaseInstanaClient, register_as_tool
|
|
27
|
+
|
|
28
|
+
# Helper function for debug printing
|
|
29
|
+
def debug_print(*args, **kwargs):
|
|
30
|
+
"""Print debug information to stderr instead of stdout"""
|
|
31
|
+
print(*args, file=sys.stderr, **kwargs)
|
|
32
|
+
|
|
33
|
+
class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
34
|
+
"""Tools for application metrics in Instana MCP."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, read_token: str, base_url: str):
|
|
37
|
+
"""Initialize the Application Metrics MCP tools client."""
|
|
38
|
+
super().__init__(read_token=read_token, base_url=base_url)
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
|
|
42
|
+
# Configure the API client with the correct base URL and authentication
|
|
43
|
+
configuration = Configuration()
|
|
44
|
+
configuration.host = base_url
|
|
45
|
+
configuration.api_key['ApiKeyAuth'] = read_token
|
|
46
|
+
configuration.api_key_prefix['ApiKeyAuth'] = 'apiToken'
|
|
47
|
+
|
|
48
|
+
# Create an API client with this configuration
|
|
49
|
+
api_client = ApiClient(configuration=configuration)
|
|
50
|
+
|
|
51
|
+
# Initialize the Instana SDK's ApplicationMetricsApi with our configured client
|
|
52
|
+
self.metrics_api = ApplicationMetricsApi(api_client=api_client)
|
|
53
|
+
except Exception as e:
|
|
54
|
+
debug_print(f"Error initializing ApplicationMetricsApi: {e}")
|
|
55
|
+
traceback.print_exc(file=sys.stderr)
|
|
56
|
+
raise
|
|
57
|
+
|
|
58
|
+
@register_as_tool
|
|
59
|
+
async def get_application_data_metrics_v2(self,
|
|
60
|
+
metrics: Optional[List[Dict[str, Any]]] = None,
|
|
61
|
+
time_frame: Optional[Dict[str, int]] = None,
|
|
62
|
+
application_id: Optional[str] = None,
|
|
63
|
+
service_id: Optional[str] = None,
|
|
64
|
+
endpoint_id: Optional[str] = None,
|
|
65
|
+
ctx=None) -> Dict[str, Any]:
|
|
66
|
+
"""
|
|
67
|
+
Get application data metrics using the v2 API.
|
|
68
|
+
|
|
69
|
+
This API endpoint retrieves one or more supported aggregations of metrics for a combination of entities.
|
|
70
|
+
For example, retrieve MEAN aggregation of latency metric for an Endpoint, Service, and Application.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
metrics: List of metrics to retrieve with their aggregations
|
|
74
|
+
Example: [{"metric": "latency", "aggregation": "MEAN"}]
|
|
75
|
+
time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
|
|
76
|
+
Example: {"from": 1617994800000, "to": 1618081200000}
|
|
77
|
+
application_id: ID of the application to get metrics for (optional)
|
|
78
|
+
service_id: ID of the service to get metrics for (optional)
|
|
79
|
+
endpoint_id: ID of the endpoint to get metrics for (optional)
|
|
80
|
+
ctx: The MCP context (optional)
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Dictionary containing metrics data or error information
|
|
84
|
+
"""
|
|
85
|
+
try:
|
|
86
|
+
debug_print(f"get_application_data_metrics_v2 called with application_id={application_id}, service_id={service_id}, endpoint_id={endpoint_id}")
|
|
87
|
+
|
|
88
|
+
# Set default time range if not provided
|
|
89
|
+
if not time_frame:
|
|
90
|
+
to_time = int(datetime.now().timestamp() * 1000)
|
|
91
|
+
from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
|
|
92
|
+
time_frame = {
|
|
93
|
+
"from": from_time,
|
|
94
|
+
"to": to_time
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Set default metrics if not provided
|
|
98
|
+
if not metrics:
|
|
99
|
+
metrics = [
|
|
100
|
+
{
|
|
101
|
+
"metric": "latency",
|
|
102
|
+
"aggregation": "MEAN"
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
# Create the request body
|
|
107
|
+
request_body = {
|
|
108
|
+
"metrics": metrics,
|
|
109
|
+
"timeFrame": time_frame
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Add entity IDs if provided
|
|
113
|
+
if application_id:
|
|
114
|
+
request_body["applicationId"] = application_id
|
|
115
|
+
if service_id:
|
|
116
|
+
request_body["serviceId"] = service_id
|
|
117
|
+
if endpoint_id:
|
|
118
|
+
request_body["endpointId"] = endpoint_id
|
|
119
|
+
|
|
120
|
+
# Create the GetApplicationMetrics object
|
|
121
|
+
get_app_metrics = GetApplicationMetrics(**request_body)
|
|
122
|
+
|
|
123
|
+
# Call the get_application_data_metrics_v2 method from the SDK
|
|
124
|
+
result = self.metrics_api.get_application_data_metrics_v2(
|
|
125
|
+
get_application_metrics=get_app_metrics
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Convert the result to a dictionary
|
|
129
|
+
if hasattr(result, 'to_dict'):
|
|
130
|
+
result_dict = result.to_dict()
|
|
131
|
+
else:
|
|
132
|
+
# If it's already a dict or another format, use it as is
|
|
133
|
+
result_dict = result
|
|
134
|
+
|
|
135
|
+
debug_print(f"Result from get_application_data_metrics_v2: {result_dict}")
|
|
136
|
+
return result_dict
|
|
137
|
+
except Exception as e:
|
|
138
|
+
debug_print(f"Error in get_application_data_metrics_v2: {e}")
|
|
139
|
+
traceback.print_exc(file=sys.stderr)
|
|
140
|
+
return {"error": f"Failed to get application data metrics: {str(e)}"}
|
|
141
|
+
|
|
142
|
+
@register_as_tool
|
|
143
|
+
async def get_application_metrics(self,
|
|
144
|
+
application_ids: Optional[List[str]] = None,
|
|
145
|
+
metrics: Optional[List[Dict[str, str]]] = None,
|
|
146
|
+
time_frame: Optional[Dict[str, int]] = None,
|
|
147
|
+
fill_time_series: Optional[bool] = True,
|
|
148
|
+
ctx=None) -> Dict[str, Any]:
|
|
149
|
+
"""
|
|
150
|
+
Get metrics for specific applications.
|
|
151
|
+
|
|
152
|
+
This API endpoint retrieves one or more supported aggregations of metrics for an Application Perspective.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
application_ids: List of application IDs to get metrics for
|
|
156
|
+
metrics: List of metrics to retrieve with their aggregations
|
|
157
|
+
Example: [{"metric": "latency", "aggregation": "MEAN"}]
|
|
158
|
+
time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
|
|
159
|
+
Example: {"from": 1617994800000, "to": 1618081200000}
|
|
160
|
+
fill_time_series: Whether to fill missing data points with timestamp and value 0
|
|
161
|
+
ctx: The MCP context (optional)
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Dictionary containing application metrics data or error information
|
|
165
|
+
"""
|
|
166
|
+
try:
|
|
167
|
+
debug_print(f"get_application_metrics called with application_ids={application_ids}")
|
|
168
|
+
|
|
169
|
+
# Set default time range if not provided
|
|
170
|
+
if not time_frame:
|
|
171
|
+
to_time = int(datetime.now().timestamp() * 1000)
|
|
172
|
+
from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
|
|
173
|
+
time_frame = {
|
|
174
|
+
"from": from_time,
|
|
175
|
+
"to": to_time
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
# Set default metrics if not provided
|
|
179
|
+
if not metrics:
|
|
180
|
+
metrics = [
|
|
181
|
+
{
|
|
182
|
+
"metric": "latency",
|
|
183
|
+
"aggregation": "MEAN"
|
|
184
|
+
}
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
# Create the request body
|
|
188
|
+
request_body = {
|
|
189
|
+
"metrics": metrics,
|
|
190
|
+
"timeFrame": time_frame
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# Add application IDs if provided
|
|
194
|
+
if application_ids:
|
|
195
|
+
request_body["applicationIds"] = application_ids
|
|
196
|
+
|
|
197
|
+
# Create the GetApplications object
|
|
198
|
+
get_applications = GetApplications(**request_body)
|
|
199
|
+
|
|
200
|
+
# Call the get_application_metrics method from the SDK
|
|
201
|
+
result = self.metrics_api.get_application_metrics(
|
|
202
|
+
fill_time_series=fill_time_series,
|
|
203
|
+
get_applications=get_applications
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# Convert the result to a dictionary
|
|
207
|
+
if hasattr(result, 'to_dict'):
|
|
208
|
+
result_dict = result.to_dict()
|
|
209
|
+
else:
|
|
210
|
+
# If it's already a dict or another format, use it as is
|
|
211
|
+
result_dict = result
|
|
212
|
+
|
|
213
|
+
debug_print(f"Result from get_application_metrics: {result_dict}")
|
|
214
|
+
return result_dict
|
|
215
|
+
except Exception as e:
|
|
216
|
+
debug_print(f"Error in get_application_metrics: {e}")
|
|
217
|
+
traceback.print_exc(file=sys.stderr)
|
|
218
|
+
return {"error": f"Failed to get application metrics: {str(e)}"}
|
|
219
|
+
|
|
220
|
+
@register_as_tool
|
|
221
|
+
async def get_endpoints_metrics(self,
|
|
222
|
+
endpoint_ids: Optional[List[str]] = None,
|
|
223
|
+
metrics: Optional[List[Dict[str, str]]] = None,
|
|
224
|
+
time_frame: Optional[Dict[str, int]] = None,
|
|
225
|
+
fill_time_series: Optional[bool] = True,
|
|
226
|
+
ctx=None) -> Dict[str, Any]:
|
|
227
|
+
"""
|
|
228
|
+
Get metrics for specific endpoints.
|
|
229
|
+
|
|
230
|
+
This API endpoint retrieves one or more supported aggregations of metrics for an Endpoint.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
endpoint_ids: List of endpoint IDs to get metrics for
|
|
234
|
+
metrics: List of metrics to retrieve with their aggregations
|
|
235
|
+
Example: [{"metric": "latency", "aggregation": "MEAN"}]
|
|
236
|
+
time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
|
|
237
|
+
Example: {"from": 1617994800000, "to": 1618081200000}
|
|
238
|
+
fill_time_series: Whether to fill missing data points with timestamp and value 0
|
|
239
|
+
ctx: The MCP context (optional)
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Dictionary containing endpoint metrics data or error information
|
|
243
|
+
"""
|
|
244
|
+
try:
|
|
245
|
+
debug_print(f"get_endpoints_metrics called with endpoint_ids={endpoint_ids}")
|
|
246
|
+
|
|
247
|
+
# Set default time range if not provided
|
|
248
|
+
if not time_frame:
|
|
249
|
+
to_time = int(datetime.now().timestamp() * 1000)
|
|
250
|
+
from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
|
|
251
|
+
time_frame = {
|
|
252
|
+
"from": from_time,
|
|
253
|
+
"to": to_time
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
# Set default metrics if not provided
|
|
257
|
+
if not metrics:
|
|
258
|
+
metrics = [
|
|
259
|
+
{
|
|
260
|
+
"metric": "latency",
|
|
261
|
+
"aggregation": "MEAN"
|
|
262
|
+
}
|
|
263
|
+
]
|
|
264
|
+
|
|
265
|
+
# Create the request body
|
|
266
|
+
request_body = {
|
|
267
|
+
"metrics": metrics,
|
|
268
|
+
"timeFrame": time_frame
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
# Add endpoint IDs if provided
|
|
272
|
+
if endpoint_ids:
|
|
273
|
+
request_body["endpointIds"] = endpoint_ids
|
|
274
|
+
|
|
275
|
+
# Create the GetEndpoints object
|
|
276
|
+
get_endpoints = GetEndpoints(**request_body)
|
|
277
|
+
|
|
278
|
+
# Call the get_endpoints_metrics method from the SDK
|
|
279
|
+
result = self.metrics_api.get_endpoints_metrics(
|
|
280
|
+
fill_time_series=fill_time_series,
|
|
281
|
+
get_endpoints=get_endpoints
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
# Convert the result to a dictionary
|
|
285
|
+
if hasattr(result, 'to_dict'):
|
|
286
|
+
result_dict = result.to_dict()
|
|
287
|
+
else:
|
|
288
|
+
# If it's already a dict or another format, use it as is
|
|
289
|
+
result_dict = result
|
|
290
|
+
|
|
291
|
+
debug_print(f"Result from get_endpoints_metrics: {result_dict}")
|
|
292
|
+
return result_dict
|
|
293
|
+
except Exception as e:
|
|
294
|
+
debug_print(f"Error in get_endpoints_metrics: {e}")
|
|
295
|
+
traceback.print_exc(file=sys.stderr)
|
|
296
|
+
return {"error": f"Failed to get endpoints metrics: {str(e)}"}
|
|
297
|
+
|
|
298
|
+
@register_as_tool
|
|
299
|
+
async def get_services_metrics(self,
|
|
300
|
+
service_ids: Optional[List[str]] = None,
|
|
301
|
+
metrics: Optional[List[Dict[str, str]]] = None,
|
|
302
|
+
time_frame: Optional[Dict[str, int]] = None,
|
|
303
|
+
fill_time_series: Optional[bool] = True,
|
|
304
|
+
include_snapshot_ids: Optional[bool] = False,
|
|
305
|
+
ctx=None) -> Dict[str, Any]:
|
|
306
|
+
"""
|
|
307
|
+
Get metrics for specific services.
|
|
308
|
+
|
|
309
|
+
This API endpoint retrieves one or more supported aggregations of metrics for a Service.
|
|
310
|
+
|
|
311
|
+
Args:
|
|
312
|
+
service_ids: List of service IDs to get metrics for
|
|
313
|
+
metrics: List of metrics to retrieve with their aggregations
|
|
314
|
+
Example: [{"metric": "latency", "aggregation": "MEAN"}]
|
|
315
|
+
time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
|
|
316
|
+
Example: {"from": 1617994800000, "to": 1618081200000}
|
|
317
|
+
fill_time_series: Whether to fill missing data points with timestamp and value 0
|
|
318
|
+
include_snapshot_ids: Whether to include snapshot IDs in the results
|
|
319
|
+
ctx: The MCP context (optional)
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
Dictionary containing service metrics data or error information
|
|
323
|
+
"""
|
|
324
|
+
try:
|
|
325
|
+
debug_print(f"get_services_metrics called with service_ids={service_ids}")
|
|
326
|
+
|
|
327
|
+
# Set default time range if not provided
|
|
328
|
+
if not time_frame:
|
|
329
|
+
to_time = int(datetime.now().timestamp() * 1000)
|
|
330
|
+
from_time = to_time - (60 * 60 * 1000) # Default to 1 hour
|
|
331
|
+
time_frame = {
|
|
332
|
+
"from": from_time,
|
|
333
|
+
"to": to_time
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
# Set default metrics if not provided
|
|
337
|
+
if not metrics:
|
|
338
|
+
metrics = [
|
|
339
|
+
{
|
|
340
|
+
"metric": "latency",
|
|
341
|
+
"aggregation": "MEAN"
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
|
|
345
|
+
# Create the request body
|
|
346
|
+
request_body = {
|
|
347
|
+
"metrics": metrics,
|
|
348
|
+
"timeFrame": time_frame
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
# Add service IDs if provided
|
|
352
|
+
if service_ids:
|
|
353
|
+
request_body["serviceIds"] = service_ids
|
|
354
|
+
|
|
355
|
+
# Create the GetServices object
|
|
356
|
+
get_services = GetServices(**request_body)
|
|
357
|
+
|
|
358
|
+
# Call the get_services_metrics method from the SDK
|
|
359
|
+
result = self.metrics_api.get_services_metrics(
|
|
360
|
+
fill_time_series=fill_time_series,
|
|
361
|
+
include_snapshot_ids=include_snapshot_ids,
|
|
362
|
+
get_services=get_services
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
# Convert the result to a dictionary
|
|
366
|
+
if hasattr(result, 'to_dict'):
|
|
367
|
+
result_dict = result.to_dict()
|
|
368
|
+
else:
|
|
369
|
+
# If it's already a dict or another format, use it as is
|
|
370
|
+
result_dict = result
|
|
371
|
+
|
|
372
|
+
debug_print(f"Result from get_services_metrics: {result_dict}")
|
|
373
|
+
return result_dict
|
|
374
|
+
except Exception as e:
|
|
375
|
+
debug_print(f"Error in get_services_metrics: {e}")
|
|
376
|
+
traceback.print_exc(file=sys.stderr)
|
|
377
|
+
return {"error": f"Failed to get services metrics: {str(e)}"}
|