mcp-instana 0.3.0__py3-none-any.whl → 0.6.2__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.
@@ -42,6 +42,9 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
42
42
  )
43
43
  @with_header_auth(ApplicationResourcesApi)
44
44
  async def get_application_endpoints(self,
45
+ app_id: Optional[str] = None,
46
+ service_id: Optional[str] = None,
47
+ endpoint_id: Optional[str] = None,
45
48
  name_filter: Optional[str] = None,
46
49
  types: Optional[List[str]] = None,
47
50
  technologies: Optional[List[str]] = None,
@@ -58,6 +61,9 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
58
61
  For example, use this tool when asked about 'application endpoints', 'service endpoints', 'API endpoints in my application','endpoint id of an Endpoint', or when someone wants to 'list all endpoints'.
59
62
 
60
63
  Args:
64
+ app_id: Application ID to filter endpoints by application (optional)
65
+ service_id: Service ID to filter endpoints by service (optional)
66
+ endpoint_id: Endpoint ID to get a specific endpoint (optional)
61
67
  name_filter: Name of service to filter by (optional)
62
68
  types: List of endpoint types to filter by (optional)
63
69
  technologies: List of technologies to filter by (optional)
@@ -83,6 +89,9 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
83
89
 
84
90
  # Call the get_application_endpoints method from the SDK
85
91
  result = api_client.get_application_endpoints(
92
+ app_id=app_id,
93
+ service_id=service_id,
94
+ endpoint_id=endpoint_id,
86
95
  name_filter=name_filter,
87
96
  types=types,
88
97
  technologies=technologies,
@@ -101,7 +110,21 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
101
110
  result_dict = result
102
111
 
103
112
  logger.debug(f"Result from get_application_endpoints: {result_dict}")
104
- return result_dict
113
+
114
+ # Check if we got a single Endpoint or EndpointResult (list)
115
+ # Single Endpoint is returned when app_id, service_id, AND endpoint_id are all provided
116
+ if app_id and service_id and endpoint_id:
117
+ # Single Endpoint object returned
118
+ return {
119
+ "type": "single_endpoint",
120
+ "endpoint": result_dict
121
+ }
122
+ else:
123
+ # EndpointResult (list) returned
124
+ return {
125
+ "type": "endpoint_list",
126
+ "data": result_dict
127
+ }
105
128
  except Exception as e:
106
129
  logger.error(f"Error in get_application_endpoints: {e}", exc_info=True)
107
130
  return {"error": f"Failed to get application endpoints: {e!s}"}
@@ -112,6 +135,8 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
112
135
  )
113
136
  @with_header_auth(ApplicationResourcesApi)
114
137
  async def get_application_services(self,
138
+ app_id: Optional[str] = None,
139
+ service_id: Optional[str] = None,
115
140
  name_filter: Optional[str] = None,
116
141
  window_size: Optional[int] = None,
117
142
  to_time: Optional[int] = None,
@@ -127,6 +152,8 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
127
152
  For example, use this tool when asked about 'application services', 'microservices in my application', 'list all services', or when someone wants to 'get service information'. A use case could be to retrieve all service ids present in an Application Perspective.
128
153
 
129
154
  Args:
155
+ app_id: Application ID to filter services by application (optional)
156
+ service_id: Service ID to filter specific service (optional)
130
157
  name_filter: Name of application/service to filter by (optional)
131
158
  window_size: Size of time window in milliseconds (optional)
132
159
  to_time: End timestamp in milliseconds (optional)
@@ -151,6 +178,8 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
151
178
 
152
179
  # Call the get_application_services method from the SDK
153
180
  result = api_client.get_application_services(
181
+ app_id=app_id,
182
+ service_id=service_id,
154
183
  name_filter=name_filter,
155
184
  window_size=window_size,
156
185
  to=to_time,
@@ -169,6 +198,16 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
169
198
 
170
199
  logger.debug(f"Result from get_application_services: {result_dict}")
171
200
 
201
+ # Check if we got a single Service or ServiceResult (list)
202
+ # Single Service is returned when both app_id AND service_id are provided
203
+ if app_id and service_id:
204
+ # Single Service object returned
205
+ return {
206
+ "type": "single_service",
207
+ "service": result_dict
208
+ }
209
+
210
+ # ServiceResult (list) returned - extract and format the data
172
211
  # Extract service labels and IDs from the items
173
212
  services = []
174
213
  service_labels = []
@@ -176,14 +215,14 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
176
215
 
177
216
  for item in items:
178
217
  if isinstance(item, dict):
179
- service_id = item.get('id', '')
218
+ svc_id = item.get('id', '')
180
219
  label = item.get('label', '')
181
220
  technologies = item.get('technologies', [])
182
221
 
183
- if label and service_id:
222
+ if label and svc_id:
184
223
  service_labels.append(label)
185
224
  services.append({
186
- 'id': service_id,
225
+ 'id': svc_id,
187
226
  'label': label,
188
227
  'technologies': technologies
189
228
  })
@@ -201,6 +240,7 @@ class ApplicationResourcesMCPTools(BaseInstanaClient):
201
240
  service_labels = [service['label'] for service in limited_services]
202
241
 
203
242
  return {
243
+ "type": "service_list",
204
244
  "message": f"Found {len(services)} services in application perspectives. Showing first {len(limited_services)}:",
205
245
  "service_labels": service_labels,
206
246
  "services": limited_services,
@@ -34,6 +34,8 @@ try:
34
34
  NewApplicationConfig, #type: ignore
35
35
  NewManualServiceConfig, #type: ignore
36
36
  ServiceConfig, #type: ignore
37
+ TagFilter, #type: ignore
38
+ TagFilterExpression, #type: ignore
37
39
  )
38
40
  except ImportError as e:
39
41
  print(f"Error importing Instana SDK: {e}", file=sys.stderr)
@@ -232,6 +234,40 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
232
234
  logger.debug(f"Error importing NewApplicationConfig: {e}")
233
235
  return {"error": f"Failed to import NewApplicationConfig: {e!s}"}
234
236
 
237
+ # Convert nested tagFilterExpression to model objects
238
+ if 'tagFilterExpression' in request_body and isinstance(request_body['tagFilterExpression'], dict):
239
+ try:
240
+ tag_expr = request_body['tagFilterExpression']
241
+ logger.debug(f"Converting tagFilterExpression: {tag_expr}")
242
+
243
+ # If it's an EXPRESSION type with elements, convert each element
244
+ if tag_expr.get('type') == 'EXPRESSION' and 'elements' in tag_expr:
245
+ converted_elements = []
246
+ for element in tag_expr['elements']:
247
+ if isinstance(element, dict):
248
+ # Remove conflicting fields before creating TagFilter
249
+ element_copy = element.copy()
250
+ element_copy.pop('value', None)
251
+ element_copy.pop('key', None)
252
+ converted_elements.append(TagFilter(**element_copy))
253
+ else:
254
+ converted_elements.append(element)
255
+ tag_expr['elements'] = converted_elements
256
+ request_body['tagFilterExpression'] = TagFilterExpression(**tag_expr)
257
+ # If it's a TAG_FILTER type, convert directly
258
+ elif tag_expr.get('type') == 'TAG_FILTER':
259
+ tag_expr_copy = tag_expr.copy()
260
+ tag_expr_copy.pop('value', None)
261
+ tag_expr_copy.pop('key', None)
262
+ request_body['tagFilterExpression'] = TagFilter(**tag_expr_copy)
263
+ else:
264
+ request_body['tagFilterExpression'] = TagFilterExpression(**tag_expr)
265
+
266
+ logger.debug("Successfully converted tagFilterExpression to model objects")
267
+ except Exception as e:
268
+ logger.debug(f"Error converting tagFilterExpression: {e}")
269
+ return {"error": f"Failed to convert tagFilterExpression: {e!s}"}
270
+
235
271
  # Create an NewApplicationConfig object from the request body
236
272
  try:
237
273
  logger.debug(f"Creating NewApplicationConfig with params: {request_body}")
@@ -466,6 +502,40 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
466
502
  logger.debug(f"Error importing ApplicationConfig: {e}")
467
503
  return {"error": f"Failed to import ApplicationConfig: {e!s}"}
468
504
 
505
+ # Convert nested tagFilterExpression to model objects
506
+ if 'tagFilterExpression' in request_body and isinstance(request_body['tagFilterExpression'], dict):
507
+ try:
508
+ tag_expr = request_body['tagFilterExpression']
509
+ logger.debug(f"Converting tagFilterExpression: {tag_expr}")
510
+
511
+ # If it's an EXPRESSION type with elements, convert each element
512
+ if tag_expr.get('type') == 'EXPRESSION' and 'elements' in tag_expr:
513
+ converted_elements = []
514
+ for element in tag_expr['elements']:
515
+ if isinstance(element, dict):
516
+ # Remove conflicting fields before creating TagFilter
517
+ element_copy = element.copy()
518
+ element_copy.pop('value', None)
519
+ element_copy.pop('key', None)
520
+ converted_elements.append(TagFilter(**element_copy))
521
+ else:
522
+ converted_elements.append(element)
523
+ tag_expr['elements'] = converted_elements
524
+ request_body['tagFilterExpression'] = TagFilterExpression(**tag_expr)
525
+ # If it's a TAG_FILTER type, convert directly
526
+ elif tag_expr.get('type') == 'TAG_FILTER':
527
+ tag_expr_copy = tag_expr.copy()
528
+ tag_expr_copy.pop('value', None)
529
+ tag_expr_copy.pop('key', None)
530
+ request_body['tagFilterExpression'] = TagFilter(**tag_expr_copy)
531
+ else:
532
+ request_body['tagFilterExpression'] = TagFilterExpression(**tag_expr)
533
+
534
+ logger.debug("Successfully converted tagFilterExpression to model objects")
535
+ except Exception as e:
536
+ logger.debug(f"Error converting tagFilterExpression: {e}")
537
+ return {"error": f"Failed to convert tagFilterExpression: {e!s}"}
538
+
469
539
  # Create an ApplicationConfig object from the request body
470
540
  try:
471
541
  logger.debug(f"Creating ApplicationConfig with params: {request_body}")
@@ -517,16 +587,23 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
517
587
  """
518
588
  try:
519
589
  debug_print("Fetching all endpoint configs")
520
- result = api_client.get_endpoint_configs()
590
+ result = api_client.get_endpoint_configs_without_preload_content()
521
591
  # Convert the result to a dictionary
522
- if hasattr(result, 'to_dict'):
523
- result_dict = result.to_dict()
524
- else:
525
- # If it's already a dict or another format, use it as is
526
- result_dict = result
527
-
528
- debug_print(f"Result from get_endpoint_configs: {result_dict}")
529
- return result_dict
592
+ import json
593
+ try:
594
+ response_text=result.data.decode('utf-8')
595
+ json_data=json.loads(response_text)
596
+ if isinstance(json_data, list):
597
+ result_dict=json_data
598
+ else:
599
+ # If it's a single object, wrap it in a list
600
+ result_dict=[json_data] if json_data else []
601
+ debug_print("Successfully retrieved endpoint configs data")
602
+ return result_dict
603
+ except (json.JSONDecodeError, AttributeError) as json_err:
604
+ error_message = f"Failed to parse JSON response: {json_err}"
605
+ logger.error(error_message)
606
+ return [{"error": error_message}]
530
607
 
531
608
  except Exception as e:
532
609
  debug_print(f"Error in get_endpoint_configs: {e}")
@@ -870,16 +947,24 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
870
947
  """
871
948
  try:
872
949
  debug_print("Fetching all manual configs")
873
- result = api_client.get_all_manual_service_configs()
950
+ result = api_client.get_all_manual_service_configs_without_preload_content()
874
951
  # Convert the result to a dictionary
875
- if hasattr(result, 'to_dict'):
876
- result_dict = result.to_dict()
877
- else:
878
- # If it's already a dict or another format, use it as is
879
- result_dict = result
880
-
881
- debug_print(f"Result from get_all_manual_service_configs: {result_dict}")
882
- return result_dict
952
+ import json
953
+ try:
954
+ response_text=result.data.decode('utf-8')
955
+ json_data=json.loads(response_text)
956
+ logger.debug("Successfully retrieved manual service configs data")
957
+ if isinstance(json_data, list):
958
+ result_dict=json_data
959
+ else:
960
+ # If it's a single object, wrap it in a list
961
+ result_dict=[json_data] if json_data else []
962
+ debug_print("Successfully retrieved manual service configs data")
963
+ return result_dict
964
+ except (json.JSONDecodeError, AttributeError) as json_err:
965
+ error_message = f"Failed to parse JSON response: {json_err}"
966
+ logger.error(error_message)
967
+ return [{"error": error_message}]
883
968
 
884
969
  except Exception as e:
885
970
  debug_print(f"Error in get_all_manual_service_configs: {e}")
@@ -975,20 +1060,38 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
975
1060
  logger.debug(f"Error importing NewManualServiceConfig: {e}")
976
1061
  return {"error": f"Failed to import NewManualServiceConfig: {e!s}"}
977
1062
 
978
- # Create an NewManualServiceConfig object from the request body
1063
+ # Convert tagFilterExpression dict to TagFilter object with all required fields
1064
+ if 'tagFilterExpression' in request_body and isinstance(request_body['tagFilterExpression'], dict):
1065
+ try:
1066
+ tag_filter_dict = request_body['tagFilterExpression']
1067
+ logger.debug(f"Converting tagFilterExpression to TagFilter object: {tag_filter_dict}")
1068
+
1069
+ # Use TagFilter.from_dict() which properly handles all fields including aliases
1070
+ tag_filter = TagFilter.from_dict(tag_filter_dict)
1071
+ request_body['tagFilterExpression'] = tag_filter
1072
+ logger.debug("Successfully converted tagFilterExpression to TagFilter object")
1073
+ except Exception as e:
1074
+ logger.debug(f"Error converting tagFilterExpression: {e}")
1075
+ return {"error": f"Failed to convert tagFilterExpression: {e!s}"}
1076
+
1077
+ # Create NewManualServiceConfig object
1078
+ logger.debug("Creating NewManualServiceConfig object")
979
1079
  try:
980
- logger.debug(f"Creating NewManualServiceConfig with params: {request_body}")
981
1080
  config_object = NewManualServiceConfig(**request_body)
982
- logger.debug("Successfully created manual service config object")
1081
+ logger.debug("Successfully created NewManualServiceConfig object")
983
1082
  except Exception as e:
984
1083
  logger.debug(f"Error creating NewManualServiceConfig: {e}")
985
1084
  return {"error": f"Failed to create config object: {e!s}"}
986
1085
 
987
- # Call the add_manual_service_config method from the SDK
1086
+ # Call the add_manual_service_config method from the SDK with the config object
988
1087
  logger.debug("Calling add_manual_service_config with config object")
989
- result = api_client.add_manual_service_config(
990
- new_manual_service_config=config_object
991
- )
1088
+ try:
1089
+ result = api_client.add_manual_service_config(
1090
+ new_manual_service_config=config_object
1091
+ )
1092
+ except Exception as e:
1093
+ logger.debug(f"Error calling add_manual_service_config: {e}")
1094
+ return {"error": f"Failed to create config object: {e!s}"}
992
1095
 
993
1096
  # Convert the result to a dictionary
994
1097
  if hasattr(result, 'to_dict'):
@@ -1141,22 +1244,21 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1141
1244
  logger.debug(f"Error importing ManualServiceConfig: {e}")
1142
1245
  return {"error": f"Failed to import ManualServiceConfig: {e!s}"}
1143
1246
 
1144
- # Create an ManualServiceConfig object from the request body
1247
+ # Keep tagFilterExpression as dictionary - SDK will handle serialization
1248
+ if 'tagFilterExpression' in request_body and isinstance(request_body['tagFilterExpression'], dict):
1249
+ logger.debug(f"tagFilterExpression will be passed as dict: {request_body['tagFilterExpression']}")
1250
+
1251
+ # Call the update_manual_service_config method from the SDK directly with dict
1252
+ logger.debug("Calling update_manual_service_config with request body")
1145
1253
  try:
1146
- logger.debug(f"Creating ManualServiceConfig with params: {request_body}")
1147
- config_object = ManualServiceConfig(**request_body)
1148
- logger.debug("Successfully update manual service config object")
1254
+ result = api_client.update_manual_service_config(
1255
+ id=id,
1256
+ manual_service_config=request_body
1257
+ )
1149
1258
  except Exception as e:
1150
- logger.debug(f"Error creating ManualServiceConfig: {e}")
1259
+ logger.debug(f"Error calling update_manual_service_config: {e}")
1151
1260
  return {"error": f"Failed to update manual config object: {e!s}"}
1152
1261
 
1153
- # Call the update_manual_service_config method from the SDK
1154
- logger.debug("Calling update_manual_service_config with config object")
1155
- result = api_client.update_manual_service_config(
1156
- id=id,
1157
- manual_service_config=config_object
1158
- )
1159
-
1160
1262
  # Convert the result to a dictionary
1161
1263
  if hasattr(result, 'to_dict'):
1162
1264
  result_dict = result.to_dict()
@@ -1421,7 +1523,9 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1421
1523
  # Create an ServiceConfig object from the request body
1422
1524
  try:
1423
1525
  logger.debug(f"Creating ServiceConfig with params: {request_body}")
1424
- config_object = ServiceConfig(**request_body)
1526
+ request_body_with_id = dict(request_body)
1527
+ request_body_with_id.setdefault("id", "temp-id")
1528
+ config_object = ServiceConfig(**request_body_with_id)
1425
1529
  logger.debug("Successfully add service config object")
1426
1530
  except Exception as e:
1427
1531
  logger.debug(f"Error creating ServiceConfig: {e}")
@@ -1432,7 +1536,6 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1432
1536
  result = api_client.add_service_config(
1433
1537
  service_config=config_object
1434
1538
  )
1435
-
1436
1539
  # Convert the result to a dictionary
1437
1540
  if hasattr(result, 'to_dict'):
1438
1541
  result_dict = result.to_dict()
@@ -1495,7 +1598,6 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1495
1598
  request_body = parsed_payload
1496
1599
  except json.JSONDecodeError as e:
1497
1600
  logger.debug(f"JSON parsing failed: {e}, trying with quotes replaced")
1498
-
1499
1601
  # Try replacing single quotes with double quotes
1500
1602
  fixed_payload = payload.replace("'", "\"")
1501
1603
  try:
@@ -1533,7 +1635,10 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1533
1635
  # Create an ServiceConfig object from the request body
1534
1636
  try:
1535
1637
  logger.debug(f"Creating ServiceConfig with params: {request_body}")
1536
- config_object = [ServiceConfig(**request_body)]
1638
+ configs = request_body.get("serviceConfigs")
1639
+ if not isinstance(configs, list):
1640
+ return [{"error": "serviceConfigs must be a list"}]
1641
+ config_object = [ServiceConfig(**item) for item in configs]
1537
1642
  logger.debug("Successfully replace all manual service config object")
1538
1643
  except Exception as e:
1539
1644
  logger.debug(f"Error creating ServiceConfig: {e}")
@@ -1541,22 +1646,22 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1541
1646
 
1542
1647
  # Call the replace_all method from the SDK
1543
1648
  logger.debug("Calling replace_all with config object")
1544
- result = api_client.replace_all(
1649
+ result = api_client.replace_all_without_preload_content(
1545
1650
  service_config=config_object
1546
1651
  )
1547
1652
 
1548
1653
  # Convert the result to a list of dictionaries
1549
- if hasattr(result, 'to_dict'):
1550
- result_dict = result.to_dict()
1551
- else:
1552
- # If it's already a dict or another format, use it as is
1553
- result_dict = result or {
1554
- "success": True,
1555
- "message": "replace all service config"
1556
- }
1654
+ import json
1655
+ try:
1656
+ response_text = result.data.decode('utf-8')
1657
+ result_dict = json.loads(response_text)
1658
+ logger.debug("Successfully replaced all service configs.")
1659
+ return result_dict
1660
+ except (json.JSONDecodeError, AttributeError) as json_err:
1661
+ error_message = f"Failed to parse JSON response: {json_err}"
1662
+ logger.error(error_message)
1663
+ return [{"error": error_message}]
1557
1664
 
1558
- logger.debug(f"Result from replace_all: {result_dict}")
1559
- return [result_dict]
1560
1665
  except Exception as e:
1561
1666
  logger.error(f"Error in replace_all: {e}")
1562
1667
  return [{"error": f"Failed to replace all service config: {e!s}"}]
@@ -1590,14 +1695,33 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1590
1695
  if not request_body:
1591
1696
  return {"error": "The list of service configuration IDs cannot be empty."}
1592
1697
 
1593
- result = api_client.order_service_config(
1594
- request_body=request_body
1698
+ response = api_client.order_service_config_with_http_info(
1699
+ request_body=request_body,
1700
+ _content_type='application/json',
1595
1701
  )
1596
1702
 
1597
- # Convert result to dict if needed
1598
- if hasattr(result, 'to_dict'):
1599
- return result.to_dict()
1600
- return result
1703
+ status = getattr(response, 'status', None)
1704
+ data = getattr(response, 'data', None)
1705
+
1706
+ if hasattr(data, 'to_dict'):
1707
+ payload = data.to_dict()
1708
+ elif data is None:
1709
+ payload = None
1710
+ else:
1711
+ payload = data
1712
+
1713
+ if status == 204 or payload is None:
1714
+ return {
1715
+ "success": True,
1716
+ "status": status,
1717
+ "message": "Service configs reordered successfully"
1718
+ }
1719
+
1720
+ return {
1721
+ "success": True,
1722
+ "status": status,
1723
+ "data": payload
1724
+ }
1601
1725
 
1602
1726
  except Exception as e:
1603
1727
  debug_print(f"Error in order_service_config: {e}")
@@ -1725,7 +1849,7 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1725
1849
  """
1726
1850
  try:
1727
1851
  if not payload or not id:
1728
- return [{"error": "missing arguments"}]
1852
+ return {"error": "missing arguments"}
1729
1853
 
1730
1854
  # Parse the payload if it's a string
1731
1855
  if isinstance(payload, str):
@@ -1754,10 +1878,10 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1754
1878
  request_body = parsed_payload
1755
1879
  except (SyntaxError, ValueError) as e2:
1756
1880
  logger.debug(f"Failed to parse payload string: {e2}")
1757
- return [{"error": f"Invalid payload format: {e2}", "payload": payload}]
1881
+ return {"error": f"Invalid payload format: {e2}", "payload": payload}
1758
1882
  except Exception as e:
1759
1883
  logger.debug(f"Error parsing payload string: {e}")
1760
- return [{"error": f"Failed to parse payload: {e}", "payload": payload}]
1884
+ return {"error": f"Failed to parse payload: {e}", "payload": payload}
1761
1885
  else:
1762
1886
  # If payload is already a dictionary, use it directly
1763
1887
  logger.debug("Using provided payload dictionary")
@@ -1771,16 +1895,16 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1771
1895
  logger.debug("Successfully imported ServiceConfig")
1772
1896
  except ImportError as e:
1773
1897
  logger.debug(f"Error importing ServiceConfig: {e}")
1774
- return [{"error": f"Failed to import ServiceConfig: {e!s}"}]
1898
+ return {"error": f"Failed to import ServiceConfig: {e!s}"}
1775
1899
 
1776
1900
  # Create an ServiceConfig object from the request body
1777
1901
  try:
1778
1902
  logger.debug(f"Creating ServiceConfig with params: {request_body}")
1779
- config_object = [ServiceConfig(**request_body)]
1903
+ config_object = ServiceConfig(**request_body)
1780
1904
  logger.debug("Successfully update service config object")
1781
1905
  except Exception as e:
1782
1906
  logger.debug(f"Error creating ServiceConfig: {e}")
1783
- return [{"error": f"Failed to replace all manual config object: {e!s}"}]
1907
+ return {"error": f"Failed to update service config object: {e!s}"}
1784
1908
 
1785
1909
  # Call the put_service_config method from the SDK
1786
1910
  logger.debug("Calling put_service_config with config object")
@@ -1800,8 +1924,8 @@ class ApplicationSettingsMCPTools(BaseInstanaClient):
1800
1924
  }
1801
1925
 
1802
1926
  logger.debug(f"Result from put_service_config: {result_dict}")
1803
- return [result_dict]
1927
+ return result_dict
1804
1928
  except Exception as e:
1805
1929
  logger.error(f"Error in put_service_config: {e}")
1806
- return [{"error": f"Failed to update service config: {e!s}"}]
1930
+ return {"error": f"Failed to update service config: {e!s}"}
1807
1931
 
src/core/server.py CHANGED
@@ -20,6 +20,8 @@ from src.prompts import PROMPT_REGISTRY
20
20
 
21
21
  load_dotenv()
22
22
 
23
+ from src.observability import task, workflow
24
+
23
25
  # Configure logging
24
26
  logging.basicConfig(
25
27
  level=logging.INFO, # Default level, can be overridden
@@ -404,6 +406,7 @@ def get_enabled_client_configs(enabled_categories: str):
404
406
  logger.warning(f"Unknown category '{category}'")
405
407
  return enabled_configs
406
408
 
409
+ @workflow(name="instana_mcp_workflow")
407
410
  def main():
408
411
  """Main entry point for the MCP server."""
409
412
  try: