claude-mpm 5.1.9__py3-none-any.whl → 5.4.3__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 (131) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/PM_INSTRUCTIONS.md +46 -0
  3. claude_mpm/agents/agent_loader.py +10 -17
  4. claude_mpm/agents/templates/circuit-breakers.md +138 -1
  5. claude_mpm/cli/commands/agent_state_manager.py +8 -17
  6. claude_mpm/cli/commands/configure.py +1046 -149
  7. claude_mpm/cli/commands/configure_agent_display.py +13 -6
  8. claude_mpm/cli/commands/mpm_init/core.py +158 -1
  9. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  10. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  11. claude_mpm/cli/commands/summarize.py +413 -0
  12. claude_mpm/cli/executor.py +8 -0
  13. claude_mpm/cli/parsers/base_parser.py +5 -0
  14. claude_mpm/cli/startup.py +60 -53
  15. claude_mpm/commands/{mpm-ticket-organize.md → mpm-organize.md} +4 -5
  16. claude_mpm/config/agent_sources.py +27 -0
  17. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  18. claude_mpm/core/socketio_pool.py +3 -3
  19. claude_mpm/core/unified_agent_registry.py +5 -15
  20. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  21. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-313.pyc +0 -0
  22. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  23. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  24. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  25. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  26. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  27. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  28. claude_mpm/hooks/claude_hooks/event_handlers.py +35 -2
  29. claude_mpm/hooks/claude_hooks/hook_handler.py +4 -0
  30. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  31. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  32. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  33. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  34. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  35. claude_mpm/hooks/claude_hooks/services/connection_manager.py +4 -0
  36. claude_mpm/scripts/launch_monitor.py +93 -13
  37. claude_mpm/services/agents/agent_recommendation_service.py +279 -0
  38. claude_mpm/services/agents/deployment/agent_template_builder.py +3 -2
  39. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +322 -53
  40. claude_mpm/services/agents/git_source_manager.py +20 -0
  41. claude_mpm/services/agents/sources/git_source_sync_service.py +8 -1
  42. claude_mpm/services/agents/toolchain_detector.py +6 -5
  43. claude_mpm/services/analysis/__init__.py +11 -1
  44. claude_mpm/services/analysis/clone_detector.py +1030 -0
  45. claude_mpm/services/command_deployment_service.py +0 -2
  46. claude_mpm/services/event_bus/config.py +3 -1
  47. claude_mpm/services/monitor/daemon.py +9 -2
  48. claude_mpm/services/monitor/daemon_manager.py +39 -3
  49. claude_mpm/services/monitor/server.py +225 -19
  50. claude_mpm/services/socketio/event_normalizer.py +15 -1
  51. claude_mpm/services/socketio/server/core.py +160 -21
  52. claude_mpm/services/version_control/git_operations.py +103 -0
  53. claude_mpm/utils/agent_filters.py +17 -44
  54. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.3.dist-info}/METADATA +1 -77
  55. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.3.dist-info}/RECORD +59 -114
  56. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.3.dist-info}/entry_points.txt +0 -2
  57. claude_mpm/dashboard/analysis_runner.py +0 -455
  58. claude_mpm/dashboard/index.html +0 -13
  59. claude_mpm/dashboard/open_dashboard.py +0 -66
  60. claude_mpm/dashboard/static/css/activity.css +0 -1958
  61. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  62. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  63. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  64. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  65. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  66. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  67. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  68. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  69. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  70. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  71. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  72. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  73. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  74. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  75. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  76. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  77. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  78. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  79. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  80. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  81. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  82. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  83. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  84. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  85. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  86. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  87. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  88. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  89. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  90. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  91. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  92. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  93. claude_mpm/dashboard/templates/code_simple.html +0 -153
  94. claude_mpm/dashboard/templates/index.html +0 -606
  95. claude_mpm/dashboard/test_dashboard.html +0 -372
  96. claude_mpm/scripts/mcp_server.py +0 -75
  97. claude_mpm/scripts/mcp_wrapper.py +0 -39
  98. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  99. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  100. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  101. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  102. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  103. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  104. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  105. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  106. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  107. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  108. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  109. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  110. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  111. claude_mpm/services/mcp_gateway/main.py +0 -589
  112. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  113. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  114. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  115. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  116. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  117. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  118. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  119. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  120. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  121. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  122. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  123. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  124. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  125. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  126. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  127. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  128. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  129. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.3.dist-info}/WHEEL +0 -0
  130. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.3.dist-info}/licenses/LICENSE +0 -0
  131. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.3.dist-info}/top_level.txt +0 -0
@@ -1,36 +0,0 @@
1
- """
2
- MCP Gateway Tools Module
3
- ========================
4
-
5
- Tool adapters and implementations for the MCP Gateway service.
6
- """
7
-
8
- from .base_adapter import (
9
- BaseToolAdapter,
10
- CalculatorToolAdapter,
11
- EchoToolAdapter,
12
- SystemInfoToolAdapter,
13
- )
14
- from .document_summarizer import DocumentSummarizerTool
15
- from .kuzu_memory_service import (
16
- KuzuMemoryService,
17
- get_context,
18
- recall_memories,
19
- search_memories,
20
- store_memory,
21
- )
22
-
23
- # Ticket tools removed - using mcp-ticketer instead
24
-
25
- __all__ = [
26
- "BaseToolAdapter",
27
- "CalculatorToolAdapter",
28
- "DocumentSummarizerTool",
29
- "EchoToolAdapter",
30
- "KuzuMemoryService",
31
- "SystemInfoToolAdapter",
32
- "get_context",
33
- "recall_memories",
34
- "search_memories",
35
- "store_memory",
36
- ]
@@ -1,485 +0,0 @@
1
- """
2
- Base Tool Adapter and Example Implementations
3
- ==============================================
4
-
5
- Base class for MCP tool adapters and example implementations.
6
-
7
- Part of ISS-0035: MCP Server Implementation - Core Server and Tool Registry
8
- """
9
-
10
- from abc import ABC
11
- from datetime import datetime, timezone
12
- from typing import Any, Dict
13
-
14
- from claude_mpm.services.mcp_gateway.core.base import BaseMCPService
15
- from claude_mpm.services.mcp_gateway.core.interfaces import (
16
- IMCPToolAdapter,
17
- MCPToolDefinition,
18
- MCPToolInvocation,
19
- MCPToolResult,
20
- )
21
-
22
-
23
- class BaseToolAdapter(BaseMCPService, IMCPToolAdapter, ABC):
24
- """
25
- Base class for MCP tool adapters.
26
-
27
- WHY: This base class provides common functionality for all tool adapters,
28
- including parameter validation, error handling, and metrics tracking.
29
- Concrete tool implementations should extend this class.
30
-
31
- DESIGN DECISIONS:
32
- - Provide default parameter validation using JSON Schema
33
- - Include standard error handling and logging
34
- - Track execution metrics for monitoring
35
- - Support both sync and async tool implementations
36
- """
37
-
38
- def __init__(self, tool_definition: MCPToolDefinition):
39
- """
40
- Initialize the base tool adapter.
41
-
42
- Args:
43
- tool_definition: Tool definition with schema and metadata
44
- """
45
- super().__init__(f"Tool-{tool_definition.name}")
46
- self._definition = tool_definition
47
- self._initialized = False
48
-
49
- # Metrics
50
- self._metrics = {
51
- "invocations": 0,
52
- "successes": 0,
53
- "failures": 0,
54
- "total_execution_time": 0.0,
55
- "average_execution_time": 0.0,
56
- "last_invocation": None,
57
- "last_error": None,
58
- }
59
-
60
- def get_definition(self) -> MCPToolDefinition:
61
- """
62
- Get the tool definition.
63
-
64
- Returns:
65
- Tool definition with schema and metadata
66
- """
67
- return self._definition
68
-
69
- def validate_parameters(self, parameters: Dict[str, Any]) -> bool:
70
- """
71
- Validate tool parameters against schema.
72
-
73
- Default implementation performs basic JSON Schema validation.
74
- Override for custom validation logic.
75
-
76
- Args:
77
- parameters: Parameters to validate
78
-
79
- Returns:
80
- True if parameters are valid
81
- """
82
- try:
83
- # Get required parameters from schema
84
- schema = self._definition.input_schema
85
- required = schema.get("required", [])
86
- properties = schema.get("properties", {})
87
-
88
- # Check required parameters
89
- for param in required:
90
- if param not in parameters:
91
- self.log_error(f"Missing required parameter: {param}")
92
- return False
93
-
94
- # Check parameter types (basic validation)
95
- for param_name, param_value in parameters.items():
96
- if param_name in properties:
97
- expected_type = properties[param_name].get("type")
98
- if expected_type:
99
- if not self._validate_type(param_value, expected_type):
100
- self.log_error(
101
- f"Invalid type for parameter {param_name}: expected {expected_type}"
102
- )
103
- return False
104
-
105
- return True
106
-
107
- except Exception as e:
108
- self.log_error(f"Error validating parameters: {e}")
109
- return False
110
-
111
- def _validate_type(self, value: Any, expected_type: str) -> bool:
112
- """
113
- Validate a value against an expected JSON Schema type.
114
-
115
- Args:
116
- value: Value to validate
117
- expected_type: Expected type (string, number, boolean, array, object)
118
-
119
- Returns:
120
- True if type matches
121
- """
122
- type_map = {
123
- "string": str,
124
- "number": (int, float),
125
- "boolean": bool,
126
- "array": list,
127
- "object": dict,
128
- "null": type(None),
129
- }
130
-
131
- expected_python_type = type_map.get(expected_type)
132
- if expected_python_type:
133
- return isinstance(value, expected_python_type)
134
-
135
- return True # Unknown type, allow it
136
-
137
- async def initialize(self) -> bool:
138
- """
139
- Initialize the tool adapter.
140
-
141
- Default implementation marks as initialized.
142
- Override for custom initialization logic.
143
-
144
- Returns:
145
- True if initialization successful
146
- """
147
- try:
148
- self.log_info(f"Initializing tool: {self._definition.name}")
149
- self._initialized = True
150
- return True
151
-
152
- except Exception as e:
153
- self.log_error(f"Failed to initialize tool: {e}")
154
- return False
155
-
156
- async def shutdown(self) -> None:
157
- """
158
- Shutdown the tool adapter and clean up resources.
159
-
160
- Default implementation marks as not initialized.
161
- Override for custom cleanup logic.
162
- """
163
- try:
164
- self.log_info(f"Shutting down tool: {self._definition.name}")
165
- self._initialized = False
166
-
167
- except Exception as e:
168
- self.log_error(f"Error during tool shutdown: {e}")
169
-
170
- def get_metrics(self) -> Dict[str, Any]:
171
- """
172
- Get tool metrics.
173
-
174
- Returns:
175
- Metrics dictionary
176
- """
177
- return self._metrics.copy()
178
-
179
- def _update_metrics(self, success: bool, execution_time: float) -> None:
180
- """
181
- Update tool metrics after invocation.
182
-
183
- Args:
184
- success: Whether invocation was successful
185
- execution_time: Execution time in seconds
186
- """
187
- self._metrics["invocations"] += 1
188
-
189
- if success:
190
- self._metrics["successes"] += 1
191
- else:
192
- self._metrics["failures"] += 1
193
-
194
- self._metrics["total_execution_time"] += execution_time
195
- self._metrics["average_execution_time"] = (
196
- self._metrics["total_execution_time"] / self._metrics["invocations"]
197
- )
198
- self._metrics["last_invocation"] = datetime.now(timezone.utc).isoformat()
199
-
200
-
201
- class EchoToolAdapter(BaseToolAdapter):
202
- """
203
- Example tool adapter that echoes input back.
204
-
205
- This is a simple example showing how to implement a concrete tool adapter.
206
- """
207
-
208
- def __init__(self):
209
- """Initialize the echo tool."""
210
- definition = MCPToolDefinition(
211
- name="echo",
212
- description="Echoes the input message back to the user",
213
- input_schema={
214
- "type": "object",
215
- "properties": {
216
- "message": {"type": "string", "description": "The message to echo"},
217
- "uppercase": {
218
- "type": "boolean",
219
- "description": "Whether to convert to uppercase",
220
- "default": False,
221
- },
222
- },
223
- "required": ["message"],
224
- },
225
- )
226
- super().__init__(definition)
227
-
228
- async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
229
- """
230
- Invoke the echo tool.
231
-
232
- Args:
233
- invocation: Tool invocation request
234
-
235
- Returns:
236
- Tool execution result with echoed message
237
- """
238
- start_time = datetime.now(timezone.utc)
239
-
240
- try:
241
- # Get parameters
242
- message = invocation.parameters.get("message", "")
243
- uppercase = invocation.parameters.get("uppercase", False)
244
-
245
- # Process message
246
- result = message.upper() if uppercase else message
247
-
248
- # Calculate execution time
249
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
250
-
251
- # Update metrics
252
- self._update_metrics(True, execution_time)
253
-
254
- return MCPToolResult(
255
- success=True,
256
- data=result,
257
- execution_time=execution_time,
258
- metadata={"tool": "echo", "length": len(result)},
259
- )
260
-
261
- except Exception as e:
262
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
263
- self._update_metrics(False, execution_time)
264
- self._metrics["last_error"] = str(e)
265
-
266
- return MCPToolResult(
267
- success=False,
268
- error=f"Echo tool failed: {e!s}",
269
- execution_time=execution_time,
270
- )
271
-
272
-
273
- class CalculatorToolAdapter(BaseToolAdapter):
274
- """
275
- Example calculator tool adapter.
276
-
277
- Demonstrates a more complex tool with multiple operations.
278
- """
279
-
280
- def __init__(self):
281
- """Initialize the calculator tool."""
282
- definition = MCPToolDefinition(
283
- name="calculator",
284
- description="Performs basic mathematical calculations",
285
- input_schema={
286
- "type": "object",
287
- "properties": {
288
- "operation": {
289
- "type": "string",
290
- "enum": ["add", "subtract", "multiply", "divide"],
291
- "description": "The mathematical operation to perform",
292
- },
293
- "a": {"type": "number", "description": "First operand"},
294
- "b": {"type": "number", "description": "Second operand"},
295
- },
296
- "required": ["operation", "a", "b"],
297
- },
298
- output_schema={
299
- "type": "object",
300
- "properties": {
301
- "result": {
302
- "type": "number",
303
- "description": "The calculation result",
304
- },
305
- "expression": {
306
- "type": "string",
307
- "description": "The mathematical expression",
308
- },
309
- },
310
- },
311
- )
312
- super().__init__(definition)
313
-
314
- async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
315
- """
316
- Invoke the calculator tool.
317
-
318
- Args:
319
- invocation: Tool invocation request
320
-
321
- Returns:
322
- Tool execution result with calculation
323
- """
324
- start_time = datetime.now(timezone.utc)
325
-
326
- try:
327
- # Get parameters
328
- operation = invocation.parameters["operation"]
329
- a = invocation.parameters["a"]
330
- b = invocation.parameters["b"]
331
-
332
- # Perform calculation
333
- if operation == "add":
334
- result = a + b
335
- expression = f"{a} + {b} = {result}"
336
- elif operation == "subtract":
337
- result = a - b
338
- expression = f"{a} - {b} = {result}"
339
- elif operation == "multiply":
340
- result = a * b
341
- expression = f"{a} * {b} = {result}"
342
- elif operation == "divide":
343
- if b == 0:
344
- raise ValueError("Division by zero")
345
- result = a / b
346
- expression = f"{a} / {b} = {result}"
347
- else:
348
- raise ValueError(f"Unknown operation: {operation}")
349
-
350
- # Calculate execution time
351
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
352
-
353
- # Update metrics
354
- self._update_metrics(True, execution_time)
355
-
356
- return MCPToolResult(
357
- success=True,
358
- data={"result": result, "expression": expression},
359
- execution_time=execution_time,
360
- metadata={"tool": "calculator", "operation": operation},
361
- )
362
-
363
- except Exception as e:
364
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
365
- self._update_metrics(False, execution_time)
366
- self._metrics["last_error"] = str(e)
367
-
368
- return MCPToolResult(
369
- success=False,
370
- error=f"Calculator tool failed: {e!s}",
371
- execution_time=execution_time,
372
- )
373
-
374
-
375
- class SystemInfoToolAdapter(BaseToolAdapter):
376
- """
377
- Example system information tool adapter.
378
-
379
- Demonstrates async operations and system interaction.
380
- """
381
-
382
- def __init__(self):
383
- """Initialize the system info tool."""
384
- definition = MCPToolDefinition(
385
- name="system_info",
386
- description="Provides system information",
387
- input_schema={
388
- "type": "object",
389
- "properties": {
390
- "info_type": {
391
- "type": "string",
392
- "enum": ["platform", "memory", "cpu", "time"],
393
- "description": "Type of system information to retrieve",
394
- }
395
- },
396
- "required": ["info_type"],
397
- },
398
- )
399
- super().__init__(definition)
400
-
401
- async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
402
- """
403
- Invoke the system info tool.
404
-
405
- Args:
406
- invocation: Tool invocation request
407
-
408
- Returns:
409
- Tool execution result with system information
410
- """
411
- start_time = datetime.now(timezone.utc)
412
-
413
- try:
414
- import platform
415
-
416
- import psutil
417
-
418
- info_type = invocation.parameters["info_type"]
419
-
420
- if info_type == "platform":
421
- result = {
422
- "system": platform.system(),
423
- "release": platform.release(),
424
- "version": platform.version(),
425
- "machine": platform.machine(),
426
- "processor": platform.processor(),
427
- "python_version": platform.python_version(),
428
- }
429
- elif info_type == "memory":
430
- mem = psutil.virtual_memory()
431
- result = {
432
- "total": mem.total,
433
- "available": mem.available,
434
- "percent": mem.percent,
435
- "used": mem.used,
436
- "free": mem.free,
437
- }
438
- elif info_type == "cpu":
439
- result = {
440
- "count": psutil.cpu_count(),
441
- "percent": psutil.cpu_percent(interval=0.1),
442
- "freq": psutil.cpu_freq()._asdict() if psutil.cpu_freq() else None,
443
- }
444
- elif info_type == "time":
445
- result = {
446
- "current": datetime.now(timezone.utc).isoformat(),
447
- "timestamp": datetime.now(timezone.utc).timestamp(),
448
- "timezone": str(datetime.now(timezone.utc).astimezone().tzinfo),
449
- }
450
- else:
451
- raise ValueError(f"Unknown info type: {info_type}")
452
-
453
- # Calculate execution time
454
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
455
-
456
- # Update metrics
457
- self._update_metrics(True, execution_time)
458
-
459
- return MCPToolResult(
460
- success=True,
461
- data=result,
462
- execution_time=execution_time,
463
- metadata={"tool": "system_info", "info_type": info_type},
464
- )
465
-
466
- except ImportError as e:
467
- # Handle missing psutil dependency gracefully
468
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
469
- self._update_metrics(False, execution_time)
470
-
471
- return MCPToolResult(
472
- success=False,
473
- error=f"System info tool requires psutil: {e!s}",
474
- execution_time=execution_time,
475
- )
476
- except Exception as e:
477
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
478
- self._update_metrics(False, execution_time)
479
- self._metrics["last_error"] = str(e)
480
-
481
- return MCPToolResult(
482
- success=False,
483
- error=f"System info tool failed: {e!s}",
484
- execution_time=execution_time,
485
- )