mcp-instana 0.1.0__py3-none-any.whl → 0.2.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.
Files changed (67) hide show
  1. mcp_instana-0.2.0.dist-info/METADATA +1229 -0
  2. mcp_instana-0.2.0.dist-info/RECORD +59 -0
  3. {mcp_instana-0.1.0.dist-info → mcp_instana-0.2.0.dist-info}/WHEEL +1 -1
  4. mcp_instana-0.2.0.dist-info/entry_points.txt +4 -0
  5. mcp_instana-0.1.0.dist-info/LICENSE → mcp_instana-0.2.0.dist-info/licenses/LICENSE.md +3 -3
  6. src/application/__init__.py +1 -0
  7. src/{client/application_alert_config_mcp_tools.py → application/application_alert_config.py} +251 -273
  8. src/application/application_analyze.py +628 -0
  9. src/application/application_catalog.py +155 -0
  10. src/application/application_global_alert_config.py +653 -0
  11. src/{client/application_metrics_mcp_tools.py → application/application_metrics.py} +113 -131
  12. src/{client/application_resources_mcp_tools.py → application/application_resources.py} +131 -151
  13. src/application/application_settings.py +1731 -0
  14. src/application/application_topology.py +111 -0
  15. src/automation/action_catalog.py +416 -0
  16. src/automation/action_history.py +338 -0
  17. src/core/__init__.py +1 -0
  18. src/core/server.py +586 -0
  19. src/core/utils.py +213 -0
  20. src/event/__init__.py +1 -0
  21. src/event/events_tools.py +850 -0
  22. src/infrastructure/__init__.py +1 -0
  23. src/{client/infrastructure_analyze_mcp_tools.py → infrastructure/infrastructure_analyze.py} +207 -206
  24. src/{client/infrastructure_catalog_mcp_tools.py → infrastructure/infrastructure_catalog.py} +197 -265
  25. src/infrastructure/infrastructure_metrics.py +171 -0
  26. src/{client/infrastructure_resources_mcp_tools.py → infrastructure/infrastructure_resources.py} +198 -227
  27. src/{client/infrastructure_topology_mcp_tools.py → infrastructure/infrastructure_topology.py} +110 -109
  28. src/log/__init__.py +1 -0
  29. src/log/log_alert_configuration.py +331 -0
  30. src/prompts/__init__.py +16 -0
  31. src/prompts/application/__init__.py +1 -0
  32. src/prompts/application/application_alerts.py +54 -0
  33. src/prompts/application/application_catalog.py +26 -0
  34. src/prompts/application/application_metrics.py +57 -0
  35. src/prompts/application/application_resources.py +26 -0
  36. src/prompts/application/application_settings.py +75 -0
  37. src/prompts/application/application_topology.py +30 -0
  38. src/prompts/events/__init__.py +1 -0
  39. src/prompts/events/events_tools.py +161 -0
  40. src/prompts/infrastructure/infrastructure_analyze.py +72 -0
  41. src/prompts/infrastructure/infrastructure_catalog.py +53 -0
  42. src/prompts/infrastructure/infrastructure_metrics.py +45 -0
  43. src/prompts/infrastructure/infrastructure_resources.py +74 -0
  44. src/prompts/infrastructure/infrastructure_topology.py +38 -0
  45. src/prompts/settings/__init__.py +0 -0
  46. src/prompts/settings/custom_dashboard.py +157 -0
  47. src/prompts/website/__init__.py +1 -0
  48. src/prompts/website/website_analyze.py +35 -0
  49. src/prompts/website/website_catalog.py +40 -0
  50. src/prompts/website/website_configuration.py +105 -0
  51. src/prompts/website/website_metrics.py +34 -0
  52. src/settings/__init__.py +1 -0
  53. src/settings/custom_dashboard_tools.py +417 -0
  54. src/website/__init__.py +0 -0
  55. src/website/website_analyze.py +433 -0
  56. src/website/website_catalog.py +171 -0
  57. src/website/website_configuration.py +770 -0
  58. src/website/website_metrics.py +241 -0
  59. mcp_instana-0.1.0.dist-info/METADATA +0 -649
  60. mcp_instana-0.1.0.dist-info/RECORD +0 -19
  61. mcp_instana-0.1.0.dist-info/entry_points.txt +0 -3
  62. src/client/What is the sum of queue depth for all q +0 -55
  63. src/client/events_mcp_tools.py +0 -531
  64. src/client/instana_client_base.py +0 -93
  65. src/client/log_alert_configuration_mcp_tools.py +0 -316
  66. src/client/show the top 5 services with the highest +0 -28
  67. src/mcp_server.py +0 -343
src/mcp_server.py DELETED
@@ -1,343 +0,0 @@
1
- """
2
- Standalone MCP Server for Instana Events and Infrastructure Resources
3
-
4
- This module provides a dedicated MCP server that exposes Instana tools.
5
- Supports stdio and Streamable HTTP transports.
6
- """
7
-
8
- import argparse
9
- import os
10
- import sys
11
- import warnings
12
- import traceback
13
- import json
14
- from collections.abc import AsyncIterator
15
- from contextlib import asynccontextmanager
16
- from dataclasses import dataclass, fields
17
- from dotenv import load_dotenv
18
- load_dotenv()
19
-
20
- # Add the project root to the Python path
21
- current_path = os.path.abspath(__file__)
22
- project_root = os.path.dirname(os.path.dirname(current_path))
23
- if project_root not in sys.path:
24
- sys.path.insert(0, project_root)
25
-
26
- # Import the necessary modules
27
- try:
28
- from src.client.events_mcp_tools import AgentMonitoringEventsMCPTools
29
- from src.client.infrastructure_resources_mcp_tools import InfrastructureResourcesMCPTools
30
- from src.client.infrastructure_catalog_mcp_tools import InfrastructureCatalogMCPTools
31
- from src.client.application_resources_mcp_tools import ApplicationResourcesMCPTools
32
- from src.client.application_metrics_mcp_tools import ApplicationMetricsMCPTools
33
- from src.client.infrastructure_topology_mcp_tools import InfrastructureTopologyMCPTools
34
- from src.client.infrastructure_analyze_mcp_tools import InfrastructureAnalyzeMCPTools
35
- from src.client.application_alert_config_mcp_tools import ApplicationAlertMCPTools
36
-
37
- from src.client.instana_client_base import register_as_tool, MCP_TOOLS
38
- except ImportError as e:
39
- traceback.print_exc(file=sys.stderr)
40
- sys.exit(1)
41
-
42
- from mcp.server.fastmcp import FastMCP
43
-
44
- @dataclass
45
- class MCPState:
46
- """State for the MCP server."""
47
- events_client: AgentMonitoringEventsMCPTools = None
48
- infra_client: InfrastructureResourcesMCPTools = None
49
- app_resource_client: ApplicationResourcesMCPTools = None
50
- app_metrics_client: ApplicationMetricsMCPTools = None
51
- app_alert_client: ApplicationAlertMCPTools = None
52
- infra_catalog_client: InfrastructureCatalogMCPTools = None
53
- infra_topo_client: InfrastructureTopologyMCPTools = None
54
- infra_analyze_client: InfrastructureAnalyzeMCPTools = None
55
-
56
- # Global variables to store credentials for lifespan
57
- _global_token = ""
58
- _global_base_url = ""
59
-
60
- def get_client_configs():
61
- """Get client configurations dynamically from MCPState dataclass"""
62
- # Map field names to their corresponding client classes
63
- client_class_mapping = {
64
- 'events_client': AgentMonitoringEventsMCPTools,
65
- 'infra_client': InfrastructureResourcesMCPTools,
66
- 'infra_catalog_client': InfrastructureCatalogMCPTools,
67
- 'infra_topo_client': InfrastructureTopologyMCPTools,
68
- 'infra_analyze_client': InfrastructureAnalyzeMCPTools,
69
- 'app_resource_client': ApplicationResourcesMCPTools,
70
- 'app_metrics_client': ApplicationMetricsMCPTools,
71
- 'app_alert_client': ApplicationAlertMCPTools,
72
- }
73
-
74
- # Get all field names from MCPState dataclass
75
- state_fields = [field.name for field in fields(MCPState)]
76
-
77
- # Return configurations for fields that have corresponding client classes
78
- configs = []
79
- for field_name in state_fields:
80
- if field_name in client_class_mapping:
81
- configs.append((field_name, client_class_mapping[field_name]))
82
- else:
83
- print(f"Warning: No client class mapping found for field '{field_name}'", file=sys.stderr)
84
-
85
- return configs
86
-
87
- def create_clients(token: str, base_url: str, enabled_categories: str = "all") -> MCPState:
88
- """Create only the enabled Instana clients"""
89
- state = MCPState()
90
-
91
- # Get enabled client configurations
92
- enabled_client_configs = get_enabled_client_configs(enabled_categories)
93
-
94
- for attr_name, client_class in enabled_client_configs:
95
- try:
96
- client = client_class(read_token=token, base_url=base_url)
97
- setattr(state, attr_name, client)
98
- except Exception as e:
99
- print(f"Failed to create {attr_name}: {e}", file=sys.stderr)
100
- traceback.print_exc(file=sys.stderr)
101
- setattr(state, attr_name, None)
102
-
103
- return state
104
-
105
-
106
- @asynccontextmanager
107
- async def lifespan(server: FastMCP) -> AsyncIterator[MCPState]:
108
- """Set up and tear down the Instana clients."""
109
- # Use global credentials set by create_app
110
- token = _global_token or os.getenv("INSTANA_API_TOKEN", "")
111
- base_url = _global_base_url or os.getenv("INSTANA_BASE_URL", "")
112
- enabled_categories = os.getenv("INSTANA_ENABLED_TOOLS", "all")
113
-
114
- try:
115
- state = create_clients(token, base_url, enabled_categories)
116
-
117
- yield state
118
- except Exception as e:
119
- traceback.print_exc(file=sys.stderr)
120
-
121
- # Yield empty state if client creation failed
122
- yield MCPState()
123
-
124
- def create_app(instana_api_token_value: str, instana_base_url: str) -> FastMCP:
125
- global _global_token, _global_base_url
126
-
127
- try:
128
- _global_token = instana_api_token_value
129
- _global_base_url = instana_base_url
130
-
131
- server = FastMCP("Instana Tools", lifespan=lifespan)
132
-
133
- # Use the enabled categories from the environment
134
- enabled_categories = os.getenv("INSTANA_ENABLED_TOOLS", "all")
135
-
136
- # Only create and register enabled clients/tools
137
- clients_state = create_clients(instana_api_token_value, instana_base_url, enabled_categories)
138
-
139
- tools_registered = 0
140
- for tool_name, tool_func in MCP_TOOLS.items():
141
- try:
142
- client_found = False
143
- client_attr_names = [field.name for field in fields(MCPState)]
144
- for attr_name in client_attr_names:
145
- client = getattr(clients_state, attr_name, None)
146
- if client and hasattr(client, tool_name):
147
- bound_method = getattr(client, tool_name)
148
- server.tool()(bound_method)
149
- tools_registered += 1
150
- client_found = True
151
- break
152
- except Exception as e:
153
- print(f"Failed to register tool {tool_name}: {e}", file=sys.stderr)
154
- traceback.print_exc(file=sys.stderr)
155
-
156
- return server, tools_registered
157
-
158
- except Exception as e:
159
- traceback.print_exc(file=sys.stderr)
160
- fallback_server = FastMCP("Instana Tools")
161
- return fallback_server
162
-
163
- async def execute_tool(tool_name: str, arguments: dict, clients_state) -> str:
164
- """Execute a tool and return result"""
165
- try:
166
- # Get all field names from MCPState dataclass
167
- client_attr_names = [field.name for field in fields(MCPState)]
168
-
169
- for attr_name in client_attr_names:
170
- client = getattr(clients_state, attr_name, None)
171
- if client and hasattr(client, tool_name):
172
- method = getattr(client, tool_name)
173
- result = await method(**arguments)
174
- return str(result)
175
-
176
- return f"Tool {tool_name} not found"
177
- except Exception as e:
178
- return f"Error executing tool {tool_name}: {str(e)}"
179
-
180
-
181
- client_categories = {
182
- "infra": [
183
- ('infra_client', InfrastructureResourcesMCPTools),
184
- ('infra_catalog_client', InfrastructureCatalogMCPTools),
185
- ('infra_topo_client', InfrastructureTopologyMCPTools),
186
- ('infra_analyze_client', InfrastructureAnalyzeMCPTools),
187
- ],
188
- "app": [
189
- ('app_resource_client', ApplicationResourcesMCPTools),
190
- ('app_metrics_client', ApplicationMetricsMCPTools),
191
- ('app_alert_client', ApplicationAlertMCPTools),
192
- ],
193
- "events": [
194
- ('events_client', AgentMonitoringEventsMCPTools),
195
- ]
196
- }
197
-
198
- def get_enabled_client_configs(enabled_categories: str):
199
- """Get client configurations based on enabled categories"""
200
- # Use the global client_categories mapping
201
- if enabled_categories.lower() == "all":
202
- all_configs = []
203
- for category_clients in client_categories.values():
204
- all_configs.extend(category_clients)
205
- return all_configs
206
- categories = [cat.strip() for cat in enabled_categories.split(",")]
207
- enabled_configs = []
208
- for category in categories:
209
- if category in client_categories:
210
- enabled_configs.extend(client_categories[category])
211
- else:
212
- print(f"Warning: Unknown category '{category}'", file=sys.stderr)
213
- return enabled_configs
214
-
215
-
216
- def main():
217
- """Main entry point for the MCP server."""
218
- try:
219
- # Get token from environment
220
- instana_api_token_value = os.getenv("INSTANA_API_TOKEN")
221
- if not instana_api_token_value:
222
- warnings.warn(
223
- "Instana API token not provided. Some functionality will be limited. "
224
- "Provide token via --api-token argument or INSTANA_API_TOKEN environment variable."
225
- )
226
-
227
- # Get base URL from environment
228
- instana_base_url = os.getenv("INSTANA_BASE_URL")
229
-
230
- # Create and configure the MCP server
231
- parser = argparse.ArgumentParser(description="Instana MCP Server", add_help=False)
232
- parser.add_argument(
233
- "-h", "--help",
234
- action="store_true",
235
- dest="help",
236
- help="show this help message and exit"
237
- )
238
- parser.add_argument(
239
- "--transport",
240
- type=str,
241
- choices=["streamable-http","stdio"],
242
- metavar='<mode>',
243
- help="Transport mode. Choose from: streamable-http, stdio."
244
- )
245
- parser.add_argument(
246
- "--debug",
247
- action="store_true",
248
- help="Enable debug mode with additional logging"
249
- )
250
- parser.add_argument(
251
- "--disable",
252
- type=str,
253
- metavar='<categories>',
254
- help="Disable categories: Choose from (infra (infrastructure), app (application), events (event-based))."
255
- )
256
- # Check for help arguments before parsing
257
- if len(sys.argv) > 1 and any(arg in ['-h','--h','--help','-help'] for arg in sys.argv[1:]):
258
- # Check if help is combined with other arguments
259
- help_args = ['-h','--h','--help','-help']
260
- other_args = [arg for arg in sys.argv[1:] if arg not in help_args]
261
-
262
- if other_args:
263
- print("error: argument -h/--h/--help/-help: not allowed with other arguments", file=sys.stderr)
264
- sys.exit(2)
265
-
266
- # Show help and exit
267
- print("options:")
268
- for action in parser._actions:
269
- # Only print options that start with '--' and have a help string
270
- if any(opt.startswith('--') for opt in action.option_strings) and action.help:
271
- # Find the first long option
272
- long_opt = next((opt for opt in action.option_strings if opt.startswith('--')), None)
273
- metavar = action.metavar or ''
274
- opt_str = f"{long_opt} {metavar}".strip()
275
- print(f"{opt_str:<24} {action.help}")
276
- sys.exit(0)
277
-
278
- args = parser.parse_args()
279
-
280
- all_categories = {"infra", "app", "events"}
281
-
282
- # By default, enable all categories
283
- enabled = set(all_categories)
284
- invalid = set()
285
- # Remove disabled categories if specified
286
- if args.disable:
287
- disabled = set(cat.strip() for cat in args.disable.split(","))
288
- invalid = disabled - all_categories
289
- enabled = enabled - disabled
290
-
291
- if invalid:
292
- print(f"Error: Unknown category/categories: {', '.join(invalid)}")
293
- print(f"Available categories: infra, app, events")
294
- sys.exit(2)
295
-
296
- if args.disable:
297
- disabled_tool_classes = []
298
- for category in disabled:
299
- if category in client_categories:
300
- disabled_tool_classes.extend(
301
- [cls.__name__ for _, cls in client_categories[category]]
302
- )
303
- if disabled_tool_classes:
304
- print(
305
- f"The following tools are disabled: {', '.join(disabled_tool_classes)}"
306
- )
307
-
308
- os.environ["INSTANA_ENABLED_TOOLS"] = ",".join(enabled)
309
-
310
- # Create and configure the MCP server
311
- app, registered_tool_count = create_app(instana_api_token_value or "", instana_base_url or "")
312
-
313
- # Run the server with the appropriate transport
314
- if args.transport == "streamable-http":
315
- if args.debug:
316
- print(f"FastMCP instance: {app}", file=sys.stderr)
317
- print(f"Registered tools: {registered_tool_count}", file=sys.stderr)
318
- try:
319
- app.run(transport="streamable-http")
320
- except Exception as e:
321
- print(f"Failed to start HTTP server: {e}", file=sys.stderr)
322
- if args.debug:
323
- traceback.print_exc(file=sys.stderr)
324
- sys.exit(1)
325
- else:
326
- print("Starting stdio transport", file=sys.stderr)
327
- app.run(transport="stdio")
328
-
329
- except KeyboardInterrupt:
330
- print("Server stopped by user", file=sys.stderr)
331
- sys.exit(0)
332
- except Exception as e:
333
- print(f"Server error: {e}", file=sys.stderr)
334
- traceback.print_exc(file=sys.stderr)
335
- sys.exit(1)
336
-
337
- if __name__ == "__main__":
338
- try:
339
- main()
340
- except Exception as e:
341
- traceback.print_exc(file=sys.stderr)
342
- sys.exit(1)
343
-