claude-mpm 5.1.9__py3-none-any.whl → 5.4.22__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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (176) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +4 -0
  3. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +1 -1
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +290 -34
  5. claude_mpm/agents/agent_loader.py +13 -44
  6. claude_mpm/agents/templates/circuit-breakers.md +138 -1
  7. claude_mpm/cli/__main__.py +4 -0
  8. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  9. claude_mpm/cli/commands/agent_state_manager.py +8 -17
  10. claude_mpm/cli/commands/agents.py +0 -31
  11. claude_mpm/cli/commands/auto_configure.py +210 -25
  12. claude_mpm/cli/commands/config.py +88 -2
  13. claude_mpm/cli/commands/configure.py +1097 -158
  14. claude_mpm/cli/commands/configure_agent_display.py +15 -6
  15. claude_mpm/cli/commands/mpm_init/core.py +160 -46
  16. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  17. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  18. claude_mpm/cli/commands/skills.py +214 -189
  19. claude_mpm/cli/commands/summarize.py +413 -0
  20. claude_mpm/cli/executor.py +11 -3
  21. claude_mpm/cli/parsers/agents_parser.py +0 -9
  22. claude_mpm/cli/parsers/auto_configure_parser.py +0 -138
  23. claude_mpm/cli/parsers/base_parser.py +5 -0
  24. claude_mpm/cli/parsers/config_parser.py +153 -83
  25. claude_mpm/cli/parsers/skills_parser.py +3 -2
  26. claude_mpm/cli/startup.py +550 -94
  27. claude_mpm/commands/mpm-config.md +265 -0
  28. claude_mpm/commands/mpm-help.md +14 -95
  29. claude_mpm/commands/mpm-organize.md +500 -0
  30. claude_mpm/config/agent_sources.py +27 -0
  31. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  32. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  33. claude_mpm/core/framework_loader.py +4 -2
  34. claude_mpm/core/logger.py +13 -0
  35. claude_mpm/core/socketio_pool.py +3 -3
  36. claude_mpm/core/unified_agent_registry.py +5 -15
  37. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  38. claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
  39. claude_mpm/hooks/claude_hooks/hook_handler.py +6 -0
  40. claude_mpm/hooks/claude_hooks/installer.py +33 -10
  41. claude_mpm/hooks/claude_hooks/memory_integration.py +26 -9
  42. claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
  43. claude_mpm/hooks/claude_hooks/services/connection_manager.py +4 -0
  44. claude_mpm/hooks/memory_integration_hook.py +46 -1
  45. claude_mpm/init.py +0 -19
  46. claude_mpm/scripts/claude-hook-handler.sh +58 -18
  47. claude_mpm/scripts/launch_monitor.py +93 -13
  48. claude_mpm/scripts/start_activity_logging.py +0 -0
  49. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  50. claude_mpm/services/agents/agent_review_service.py +280 -0
  51. claude_mpm/services/agents/deployment/agent_discovery_service.py +2 -3
  52. claude_mpm/services/agents/deployment/agent_template_builder.py +4 -2
  53. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +78 -9
  54. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +335 -53
  55. claude_mpm/services/agents/git_source_manager.py +34 -0
  56. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  57. claude_mpm/services/agents/sources/git_source_sync_service.py +8 -1
  58. claude_mpm/services/agents/toolchain_detector.py +10 -6
  59. claude_mpm/services/analysis/__init__.py +11 -1
  60. claude_mpm/services/analysis/clone_detector.py +1030 -0
  61. claude_mpm/services/command_deployment_service.py +81 -10
  62. claude_mpm/services/event_bus/config.py +3 -1
  63. claude_mpm/services/git/git_operations_service.py +93 -8
  64. claude_mpm/services/monitor/daemon.py +9 -2
  65. claude_mpm/services/monitor/daemon_manager.py +39 -3
  66. claude_mpm/services/monitor/server.py +225 -19
  67. claude_mpm/services/self_upgrade_service.py +120 -12
  68. claude_mpm/services/skills/__init__.py +3 -0
  69. claude_mpm/services/skills/git_skill_source_manager.py +32 -2
  70. claude_mpm/services/skills/selective_skill_deployer.py +704 -0
  71. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  72. claude_mpm/services/skills_deployer.py +126 -9
  73. claude_mpm/services/socketio/event_normalizer.py +15 -1
  74. claude_mpm/services/socketio/server/core.py +160 -21
  75. claude_mpm/services/version_control/git_operations.py +103 -0
  76. claude_mpm/utils/agent_filters.py +17 -44
  77. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.22.dist-info}/METADATA +47 -84
  78. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.22.dist-info}/RECORD +82 -161
  79. claude_mpm-5.4.22.dist-info/entry_points.txt +5 -0
  80. claude_mpm-5.4.22.dist-info/licenses/LICENSE +94 -0
  81. claude_mpm-5.4.22.dist-info/licenses/LICENSE-FAQ.md +153 -0
  82. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  83. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  84. claude_mpm/agents/BASE_ENGINEER.md +0 -658
  85. claude_mpm/agents/BASE_OPS.md +0 -219
  86. claude_mpm/agents/BASE_PM.md +0 -480
  87. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  88. claude_mpm/agents/BASE_QA.md +0 -167
  89. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  90. claude_mpm/agents/base_agent.json +0 -31
  91. claude_mpm/agents/base_agent_loader.py +0 -601
  92. claude_mpm/cli/commands/agents_detect.py +0 -380
  93. claude_mpm/cli/commands/agents_recommend.py +0 -309
  94. claude_mpm/cli/ticket_cli.py +0 -35
  95. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  96. claude_mpm/commands/mpm-agents-detect.md +0 -177
  97. claude_mpm/commands/mpm-agents-list.md +0 -131
  98. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  99. claude_mpm/commands/mpm-config-view.md +0 -150
  100. claude_mpm/commands/mpm-ticket-organize.md +0 -304
  101. claude_mpm/dashboard/analysis_runner.py +0 -455
  102. claude_mpm/dashboard/index.html +0 -13
  103. claude_mpm/dashboard/open_dashboard.py +0 -66
  104. claude_mpm/dashboard/static/css/activity.css +0 -1958
  105. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  106. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  107. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  108. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  109. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  110. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  111. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  112. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  113. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  114. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  115. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  116. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  117. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  118. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  119. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  120. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  121. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  122. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  123. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  124. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  125. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  126. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  127. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  128. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  129. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  130. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  131. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  132. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  133. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  134. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  135. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  136. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  137. claude_mpm/dashboard/templates/code_simple.html +0 -153
  138. claude_mpm/dashboard/templates/index.html +0 -606
  139. claude_mpm/dashboard/test_dashboard.html +0 -372
  140. claude_mpm/scripts/mcp_server.py +0 -75
  141. claude_mpm/scripts/mcp_wrapper.py +0 -39
  142. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  143. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  144. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  145. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  146. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  147. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  148. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  149. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  150. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  151. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  152. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  153. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  154. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  155. claude_mpm/services/mcp_gateway/main.py +0 -589
  156. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  157. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  158. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  159. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  160. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  161. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  162. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  163. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  164. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  165. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  166. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  167. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  168. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  169. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  170. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  171. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  172. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  173. claude_mpm-5.1.9.dist-info/entry_points.txt +0 -10
  174. claude_mpm-5.1.9.dist-info/licenses/LICENSE +0 -21
  175. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.22.dist-info}/WHEEL +0 -0
  176. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.22.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
- )