claude-mpm 4.3.12__py3-none-any.whl → 4.3.14__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 (206) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/PM_INSTRUCTIONS.md +414 -28
  3. claude_mpm/agents/templates/data_engineer.json +39 -14
  4. claude_mpm/agents/templates/engineer.json +11 -3
  5. claude_mpm/cli/commands/agent_manager.py +3 -3
  6. claude_mpm/cli/commands/agents.py +2 -2
  7. claude_mpm/cli/commands/aggregate.py +1 -1
  8. claude_mpm/cli/commands/config.py +2 -2
  9. claude_mpm/cli/commands/configure.py +5 -5
  10. claude_mpm/cli/commands/configure_tui.py +7 -7
  11. claude_mpm/cli/commands/dashboard.py +1 -1
  12. claude_mpm/cli/commands/debug.py +5 -5
  13. claude_mpm/cli/commands/mcp.py +1 -1
  14. claude_mpm/cli/commands/mcp_command_router.py +1 -1
  15. claude_mpm/cli/commands/mcp_config.py +7 -10
  16. claude_mpm/cli/commands/mcp_external_commands.py +40 -32
  17. claude_mpm/cli/commands/mcp_install_commands.py +38 -10
  18. claude_mpm/cli/commands/mcp_setup_external.py +143 -102
  19. claude_mpm/cli/commands/monitor.py +2 -2
  20. claude_mpm/cli/commands/mpm_init_handler.py +1 -1
  21. claude_mpm/cli/commands/run.py +54 -2
  22. claude_mpm/cli/commands/search.py +41 -34
  23. claude_mpm/cli/interactive/agent_wizard.py +6 -2
  24. claude_mpm/cli/parsers/mcp_parser.py +1 -3
  25. claude_mpm/cli/parsers/search_parser.py +10 -4
  26. claude_mpm/cli/startup_logging.py +158 -5
  27. claude_mpm/cli/utils.py +1 -1
  28. claude_mpm/core/agent_registry.py +2 -2
  29. claude_mpm/core/agent_session_manager.py +8 -8
  30. claude_mpm/core/api_validator.py +6 -4
  31. claude_mpm/core/base_service.py +10 -10
  32. claude_mpm/core/cache.py +5 -5
  33. claude_mpm/core/config_constants.py +1 -1
  34. claude_mpm/core/container.py +1 -1
  35. claude_mpm/core/error_handler.py +2 -2
  36. claude_mpm/core/file_utils.py +1 -1
  37. claude_mpm/core/framework_loader.py +3 -3
  38. claude_mpm/core/hook_manager.py +8 -6
  39. claude_mpm/core/instruction_reinforcement_hook.py +2 -2
  40. claude_mpm/core/interactive_session.py +3 -1
  41. claude_mpm/core/lazy.py +3 -3
  42. claude_mpm/core/log_manager.py +16 -12
  43. claude_mpm/core/logger.py +16 -11
  44. claude_mpm/core/optimized_agent_loader.py +6 -6
  45. claude_mpm/core/output_style_manager.py +1 -1
  46. claude_mpm/core/pm_hook_interceptor.py +3 -3
  47. claude_mpm/core/service_registry.py +1 -1
  48. claude_mpm/core/session_manager.py +11 -9
  49. claude_mpm/core/socketio_pool.py +13 -13
  50. claude_mpm/core/types.py +2 -2
  51. claude_mpm/core/unified_agent_registry.py +2 -2
  52. claude_mpm/core/unified_paths.py +1 -1
  53. claude_mpm/dashboard/analysis_runner.py +4 -4
  54. claude_mpm/dashboard/api/simple_directory.py +1 -1
  55. claude_mpm/generators/agent_profile_generator.py +4 -2
  56. claude_mpm/hooks/base_hook.py +2 -2
  57. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  58. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  59. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  60. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-313.pyc +0 -0
  61. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  62. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  63. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  64. claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
  65. claude_mpm/hooks/claude_hooks/event_handlers.py +12 -12
  66. claude_mpm/hooks/claude_hooks/hook_handler.py +4 -4
  67. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +3 -3
  68. claude_mpm/hooks/claude_hooks/hook_handler_original.py +15 -14
  69. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +4 -4
  70. claude_mpm/hooks/claude_hooks/installer.py +3 -3
  71. claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
  72. claude_mpm/hooks/claude_hooks/response_tracking.py +3 -3
  73. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  74. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-313.pyc +0 -0
  75. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  76. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  77. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  78. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  79. claude_mpm/hooks/claude_hooks/services/connection_manager.py +8 -5
  80. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +3 -3
  81. claude_mpm/hooks/claude_hooks/services/state_manager.py +8 -7
  82. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
  83. claude_mpm/hooks/claude_hooks/tool_analysis.py +2 -2
  84. claude_mpm/hooks/memory_integration_hook.py +1 -1
  85. claude_mpm/hooks/tool_call_interceptor.py +2 -2
  86. claude_mpm/models/agent_session.py +7 -5
  87. claude_mpm/scripts/mcp_server.py +0 -0
  88. claude_mpm/scripts/start_activity_logging.py +0 -0
  89. claude_mpm/services/__init__.py +1 -1
  90. claude_mpm/services/agent_capabilities_service.py +1 -1
  91. claude_mpm/services/agents/agent_builder.py +3 -3
  92. claude_mpm/services/agents/deployment/agent_deployment.py +2 -1
  93. claude_mpm/services/agents/deployment/agent_discovery_service.py +9 -3
  94. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +5 -5
  95. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +3 -1
  96. claude_mpm/services/agents/deployment/agent_metrics_collector.py +1 -1
  97. claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
  98. claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
  99. claude_mpm/services/agents/deployment/agent_template_builder.py +1 -1
  100. claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
  101. claude_mpm/services/agents/deployment/deployment_wrapper.py +2 -3
  102. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +1 -1
  103. claude_mpm/services/agents/loading/agent_profile_loader.py +5 -3
  104. claude_mpm/services/agents/loading/base_agent_manager.py +2 -2
  105. claude_mpm/services/agents/local_template_manager.py +6 -6
  106. claude_mpm/services/agents/management/agent_management_service.py +3 -3
  107. claude_mpm/services/agents/memory/content_manager.py +3 -3
  108. claude_mpm/services/agents/memory/memory_format_service.py +2 -2
  109. claude_mpm/services/agents/memory/template_generator.py +3 -3
  110. claude_mpm/services/agents/registry/modification_tracker.py +2 -2
  111. claude_mpm/services/async_session_logger.py +3 -3
  112. claude_mpm/services/claude_session_logger.py +4 -4
  113. claude_mpm/services/cli/agent_listing_service.py +3 -1
  114. claude_mpm/services/cli/agent_validation_service.py +2 -0
  115. claude_mpm/services/cli/memory_crud_service.py +11 -6
  116. claude_mpm/services/cli/memory_output_formatter.py +1 -1
  117. claude_mpm/services/cli/session_manager.py +15 -11
  118. claude_mpm/services/core/memory_manager.py +81 -23
  119. claude_mpm/services/core/path_resolver.py +1 -1
  120. claude_mpm/services/diagnostics/checks/installation_check.py +1 -1
  121. claude_mpm/services/event_aggregator.py +4 -2
  122. claude_mpm/services/event_bus/direct_relay.py +5 -3
  123. claude_mpm/services/event_bus/event_bus.py +3 -3
  124. claude_mpm/services/event_bus/relay.py +6 -4
  125. claude_mpm/services/events/consumers/dead_letter.py +5 -3
  126. claude_mpm/services/events/core.py +3 -3
  127. claude_mpm/services/events/producers/hook.py +6 -6
  128. claude_mpm/services/events/producers/system.py +8 -8
  129. claude_mpm/services/exceptions.py +5 -5
  130. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -3
  131. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
  132. claude_mpm/services/hook_installer_service.py +1 -1
  133. claude_mpm/services/infrastructure/context_preservation.py +6 -4
  134. claude_mpm/services/infrastructure/daemon_manager.py +2 -2
  135. claude_mpm/services/infrastructure/logging.py +2 -2
  136. claude_mpm/services/mcp_config_manager.py +175 -30
  137. claude_mpm/services/mcp_gateway/__init__.py +1 -1
  138. claude_mpm/services/mcp_gateway/auto_configure.py +3 -3
  139. claude_mpm/services/mcp_gateway/config/config_loader.py +1 -1
  140. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  141. claude_mpm/services/mcp_gateway/core/base.py +2 -2
  142. claude_mpm/services/mcp_gateway/main.py +21 -7
  143. claude_mpm/services/mcp_gateway/registry/tool_registry.py +10 -8
  144. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
  145. claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
  146. claude_mpm/services/mcp_gateway/server/stdio_server.py +5 -2
  147. claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
  148. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +7 -5
  149. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +190 -137
  150. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +5 -5
  151. claude_mpm/services/mcp_gateway/tools/hello_world.py +9 -9
  152. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +16 -16
  153. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +16 -16
  154. claude_mpm/services/memory/builder.py +7 -5
  155. claude_mpm/services/memory/indexed_memory.py +4 -4
  156. claude_mpm/services/memory/optimizer.py +6 -6
  157. claude_mpm/services/memory/router.py +3 -3
  158. claude_mpm/services/monitor/daemon.py +1 -1
  159. claude_mpm/services/monitor/daemon_manager.py +6 -6
  160. claude_mpm/services/monitor/event_emitter.py +2 -2
  161. claude_mpm/services/monitor/management/lifecycle.py +3 -1
  162. claude_mpm/services/monitor/server.py +4 -4
  163. claude_mpm/services/monitor_build_service.py +2 -2
  164. claude_mpm/services/port_manager.py +3 -1
  165. claude_mpm/services/response_tracker.py +2 -2
  166. claude_mpm/services/session_management_service.py +3 -2
  167. claude_mpm/services/socketio/client_proxy.py +2 -2
  168. claude_mpm/services/socketio/dashboard_server.py +4 -3
  169. claude_mpm/services/socketio/event_normalizer.py +11 -7
  170. claude_mpm/services/socketio/handlers/base.py +2 -2
  171. claude_mpm/services/socketio/handlers/connection.py +10 -10
  172. claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
  173. claude_mpm/services/socketio/handlers/hook.py +16 -15
  174. claude_mpm/services/socketio/migration_utils.py +1 -1
  175. claude_mpm/services/socketio/monitor_client.py +5 -5
  176. claude_mpm/services/socketio/server/broadcaster.py +9 -7
  177. claude_mpm/services/socketio/server/connection_manager.py +2 -2
  178. claude_mpm/services/socketio/server/core.py +7 -5
  179. claude_mpm/services/socketio/server/eventbus_integration.py +18 -12
  180. claude_mpm/services/socketio/server/main.py +13 -13
  181. claude_mpm/services/socketio_client_manager.py +4 -4
  182. claude_mpm/services/system_instructions_service.py +2 -2
  183. claude_mpm/services/utility_service.py +5 -2
  184. claude_mpm/services/version_control/branch_strategy.py +2 -2
  185. claude_mpm/services/version_control/git_operations.py +22 -20
  186. claude_mpm/services/version_control/semantic_versioning.py +3 -3
  187. claude_mpm/services/version_control/version_parser.py +7 -5
  188. claude_mpm/services/visualization/mermaid_generator.py +3 -1
  189. claude_mpm/storage/state_storage.py +1 -1
  190. claude_mpm/tools/code_tree_analyzer.py +23 -18
  191. claude_mpm/tools/code_tree_builder.py +2 -2
  192. claude_mpm/tools/code_tree_events.py +10 -8
  193. claude_mpm/tools/socketio_debug.py +3 -3
  194. claude_mpm/utils/agent_dependency_loader.py +6 -2
  195. claude_mpm/utils/dependency_strategies.py +8 -3
  196. claude_mpm/utils/environment_context.py +1 -1
  197. claude_mpm/utils/error_handler.py +2 -2
  198. claude_mpm/utils/file_utils.py +1 -1
  199. claude_mpm/utils/log_cleanup.py +21 -7
  200. claude_mpm/validation/agent_validator.py +2 -2
  201. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/METADATA +1 -1
  202. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/RECORD +204 -191
  203. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/WHEEL +0 -0
  204. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/entry_points.txt +0 -0
  205. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/licenses/LICENSE +0 -0
  206. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/top_level.txt +0 -0
@@ -10,14 +10,12 @@ Note: As of the latest architecture, external services are registered as separat
10
10
  MCP servers in Claude Desktop configuration, not as tools within the gateway.
11
11
  """
12
12
 
13
- import asyncio
14
13
  import json
15
14
  import subprocess
16
15
  import sys
17
16
  from pathlib import Path
18
- from typing import Any, Dict, List, Optional
17
+ from typing import Any, Dict, List
19
18
 
20
- from claude_mpm.services.mcp_gateway.core.base import BaseMCPService
21
19
  from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseMCPToolAdapter
22
20
 
23
21
 
@@ -45,7 +43,9 @@ class ExternalMCPService(BaseMCPToolAdapter):
45
43
  self._is_installed = await self._check_installation()
46
44
 
47
45
  if not self._is_installed:
48
- self.logger.warning(f"{self.package_name} not installed, attempting installation...")
46
+ self.logger.warning(
47
+ f"{self.package_name} not installed, attempting installation..."
48
+ )
49
49
  await self._install_package()
50
50
  self._is_installed = await self._check_installation()
51
51
 
@@ -67,10 +67,15 @@ class ExternalMCPService(BaseMCPToolAdapter):
67
67
  [sys.executable, "-m", self.package_name.replace("-", "_"), "--help"],
68
68
  capture_output=True,
69
69
  text=True,
70
- timeout=5
70
+ timeout=5,
71
+ check=False,
71
72
  )
72
73
  return result.returncode == 0
73
- except (subprocess.TimeoutExpired, FileNotFoundError, subprocess.CalledProcessError):
74
+ except (
75
+ subprocess.TimeoutExpired,
76
+ FileNotFoundError,
77
+ subprocess.CalledProcessError,
78
+ ):
74
79
  return False
75
80
 
76
81
  async def _install_package(self) -> bool:
@@ -81,15 +86,15 @@ class ExternalMCPService(BaseMCPToolAdapter):
81
86
  [sys.executable, "-m", "pip", "install", self.package_name],
82
87
  capture_output=True,
83
88
  text=True,
84
- timeout=30
89
+ timeout=30,
90
+ check=False,
85
91
  )
86
92
 
87
93
  if result.returncode == 0:
88
94
  self.logger.info(f"Successfully installed {self.package_name}")
89
95
  return True
90
- else:
91
- self.logger.error(f"Failed to install {self.package_name}: {result.stderr}")
92
- return False
96
+ self.logger.error(f"Failed to install {self.package_name}: {result.stderr}")
97
+ return False
93
98
 
94
99
  except Exception as e:
95
100
  self.logger.error(f"Error installing {self.package_name}: {e}")
@@ -102,7 +107,7 @@ class ExternalMCPService(BaseMCPToolAdapter):
102
107
  "description": f"External MCP service: {self.package_name}",
103
108
  "type": "external_service",
104
109
  "package": self.package_name,
105
- "installed": self._is_installed
110
+ "installed": self._is_installed,
106
111
  }
107
112
 
108
113
 
@@ -116,77 +121,103 @@ class MCPVectorSearchService(ExternalMCPService):
116
121
  def get_definition(self) -> Dict[str, Any]:
117
122
  """Get tool definition for MCP registration."""
118
123
  base_def = super().get_definition()
119
- base_def.update({
120
- "description": "Semantic code search powered by vector embeddings",
121
- "tools": [
122
- {
123
- "name": "mcp__mcp-vector-search__search_code",
124
- "description": "Search for code using semantic similarity",
125
- "inputSchema": {
126
- "type": "object",
127
- "properties": {
128
- "query": {"type": "string", "description": "The search query"},
129
- "limit": {"type": "integer", "default": 10},
130
- "similarity_threshold": {"type": "number", "default": 0.3},
131
- "language": {"type": "string"},
132
- "file_extensions": {"type": "array", "items": {"type": "string"}},
133
- "files": {"type": "string"},
134
- "class_name": {"type": "string"},
135
- "function_name": {"type": "string"}
124
+ base_def.update(
125
+ {
126
+ "description": "Semantic code search powered by vector embeddings",
127
+ "tools": [
128
+ {
129
+ "name": "mcp__mcp-vector-search__search_code",
130
+ "description": "Search for code using semantic similarity",
131
+ "inputSchema": {
132
+ "type": "object",
133
+ "properties": {
134
+ "query": {
135
+ "type": "string",
136
+ "description": "The search query",
137
+ },
138
+ "limit": {"type": "integer", "default": 10},
139
+ "similarity_threshold": {
140
+ "type": "number",
141
+ "default": 0.3,
142
+ },
143
+ "language": {"type": "string"},
144
+ "file_extensions": {
145
+ "type": "array",
146
+ "items": {"type": "string"},
147
+ },
148
+ "files": {"type": "string"},
149
+ "class_name": {"type": "string"},
150
+ "function_name": {"type": "string"},
151
+ },
152
+ "required": ["query"],
136
153
  },
137
- "required": ["query"]
138
- }
139
- },
140
- {
141
- "name": "mcp__mcp-vector-search__search_similar",
142
- "description": "Find code similar to a specific file or function",
143
- "inputSchema": {
144
- "type": "object",
145
- "properties": {
146
- "file_path": {"type": "string", "description": "Path to the file"},
147
- "function_name": {"type": "string"},
148
- "limit": {"type": "integer", "default": 10},
149
- "similarity_threshold": {"type": "number", "default": 0.3}
154
+ },
155
+ {
156
+ "name": "mcp__mcp-vector-search__search_similar",
157
+ "description": "Find code similar to a specific file or function",
158
+ "inputSchema": {
159
+ "type": "object",
160
+ "properties": {
161
+ "file_path": {
162
+ "type": "string",
163
+ "description": "Path to the file",
164
+ },
165
+ "function_name": {"type": "string"},
166
+ "limit": {"type": "integer", "default": 10},
167
+ "similarity_threshold": {
168
+ "type": "number",
169
+ "default": 0.3,
170
+ },
171
+ },
172
+ "required": ["file_path"],
150
173
  },
151
- "required": ["file_path"]
152
- }
153
- },
154
- {
155
- "name": "mcp__mcp-vector-search__search_context",
156
- "description": "Search for code based on contextual description",
157
- "inputSchema": {
158
- "type": "object",
159
- "properties": {
160
- "description": {"type": "string", "description": "Contextual description"},
161
- "focus_areas": {"type": "array", "items": {"type": "string"}},
162
- "limit": {"type": "integer", "default": 10}
174
+ },
175
+ {
176
+ "name": "mcp__mcp-vector-search__search_context",
177
+ "description": "Search for code based on contextual description",
178
+ "inputSchema": {
179
+ "type": "object",
180
+ "properties": {
181
+ "description": {
182
+ "type": "string",
183
+ "description": "Contextual description",
184
+ },
185
+ "focus_areas": {
186
+ "type": "array",
187
+ "items": {"type": "string"},
188
+ },
189
+ "limit": {"type": "integer", "default": 10},
190
+ },
191
+ "required": ["description"],
163
192
  },
164
- "required": ["description"]
165
- }
166
- },
167
- {
168
- "name": "mcp__mcp-vector-search__get_project_status",
169
- "description": "Get project indexing status and statistics",
170
- "inputSchema": {
171
- "type": "object",
172
- "properties": {},
173
- "required": []
174
- }
175
- },
176
- {
177
- "name": "mcp__mcp-vector-search__index_project",
178
- "description": "Index or reindex the project codebase",
179
- "inputSchema": {
180
- "type": "object",
181
- "properties": {
182
- "force": {"type": "boolean", "default": False},
183
- "file_extensions": {"type": "array", "items": {"type": "string"}}
193
+ },
194
+ {
195
+ "name": "mcp__mcp-vector-search__get_project_status",
196
+ "description": "Get project indexing status and statistics",
197
+ "inputSchema": {
198
+ "type": "object",
199
+ "properties": {},
200
+ "required": [],
184
201
  },
185
- "required": []
186
- }
187
- }
188
- ]
189
- })
202
+ },
203
+ {
204
+ "name": "mcp__mcp-vector-search__index_project",
205
+ "description": "Index or reindex the project codebase",
206
+ "inputSchema": {
207
+ "type": "object",
208
+ "properties": {
209
+ "force": {"type": "boolean", "default": False},
210
+ "file_extensions": {
211
+ "type": "array",
212
+ "items": {"type": "string"},
213
+ },
214
+ },
215
+ "required": [],
216
+ },
217
+ },
218
+ ],
219
+ }
220
+ )
190
221
  return base_def
191
222
 
192
223
  async def invoke(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
@@ -197,9 +228,13 @@ class MCPVectorSearchService(ExternalMCPService):
197
228
 
198
229
  # Prepare the command
199
230
  cmd = [
200
- sys.executable, "-m", "mcp_vector_search",
201
- "--tool", actual_tool,
202
- "--args", json.dumps(arguments)
231
+ sys.executable,
232
+ "-m",
233
+ "mcp_vector_search",
234
+ "--tool",
235
+ actual_tool,
236
+ "--args",
237
+ json.dumps(arguments),
203
238
  ]
204
239
 
205
240
  # Run the command
@@ -208,7 +243,8 @@ class MCPVectorSearchService(ExternalMCPService):
208
243
  capture_output=True,
209
244
  text=True,
210
245
  timeout=30,
211
- cwd=Path.cwd() # Use current working directory for project context
246
+ cwd=Path.cwd(),
247
+ check=False, # Use current working directory for project context
212
248
  )
213
249
 
214
250
  if result.returncode == 0:
@@ -235,47 +271,61 @@ class MCPBrowserService(ExternalMCPService):
235
271
  def get_definition(self) -> Dict[str, Any]:
236
272
  """Get tool definition for MCP registration."""
237
273
  base_def = super().get_definition()
238
- base_def.update({
239
- "description": "Web browsing and content extraction capabilities",
240
- "tools": [
241
- {
242
- "name": "mcp__mcp-browser__browse",
243
- "description": "Browse a webpage and extract content",
244
- "inputSchema": {
245
- "type": "object",
246
- "properties": {
247
- "url": {"type": "string", "description": "URL to browse"},
248
- "extract": {"type": "string", "description": "What to extract"}
274
+ base_def.update(
275
+ {
276
+ "description": "Web browsing and content extraction capabilities",
277
+ "tools": [
278
+ {
279
+ "name": "mcp__mcp-browser__browse",
280
+ "description": "Browse a webpage and extract content",
281
+ "inputSchema": {
282
+ "type": "object",
283
+ "properties": {
284
+ "url": {
285
+ "type": "string",
286
+ "description": "URL to browse",
287
+ },
288
+ "extract": {
289
+ "type": "string",
290
+ "description": "What to extract",
291
+ },
292
+ },
293
+ "required": ["url"],
249
294
  },
250
- "required": ["url"]
251
- }
252
- },
253
- {
254
- "name": "mcp__mcp-browser__search",
255
- "description": "Search the web",
256
- "inputSchema": {
257
- "type": "object",
258
- "properties": {
259
- "query": {"type": "string", "description": "Search query"},
260
- "num_results": {"type": "integer", "default": 10}
295
+ },
296
+ {
297
+ "name": "mcp__mcp-browser__search",
298
+ "description": "Search the web",
299
+ "inputSchema": {
300
+ "type": "object",
301
+ "properties": {
302
+ "query": {
303
+ "type": "string",
304
+ "description": "Search query",
305
+ },
306
+ "num_results": {"type": "integer", "default": 10},
307
+ },
308
+ "required": ["query"],
261
309
  },
262
- "required": ["query"]
263
- }
264
- },
265
- {
266
- "name": "mcp__mcp-browser__screenshot",
267
- "description": "Take a screenshot of a webpage",
268
- "inputSchema": {
269
- "type": "object",
270
- "properties": {
271
- "url": {"type": "string", "description": "URL to screenshot"},
272
- "full_page": {"type": "boolean", "default": False}
310
+ },
311
+ {
312
+ "name": "mcp__mcp-browser__screenshot",
313
+ "description": "Take a screenshot of a webpage",
314
+ "inputSchema": {
315
+ "type": "object",
316
+ "properties": {
317
+ "url": {
318
+ "type": "string",
319
+ "description": "URL to screenshot",
320
+ },
321
+ "full_page": {"type": "boolean", "default": False},
322
+ },
323
+ "required": ["url"],
273
324
  },
274
- "required": ["url"]
275
- }
276
- }
277
- ]
278
- })
325
+ },
326
+ ],
327
+ }
328
+ )
279
329
  return base_def
280
330
 
281
331
  async def invoke(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
@@ -286,17 +336,18 @@ class MCPBrowserService(ExternalMCPService):
286
336
 
287
337
  # Prepare the command
288
338
  cmd = [
289
- sys.executable, "-m", "mcp_browser",
290
- "--tool", actual_tool,
291
- "--args", json.dumps(arguments)
339
+ sys.executable,
340
+ "-m",
341
+ "mcp_browser",
342
+ "--tool",
343
+ actual_tool,
344
+ "--args",
345
+ json.dumps(arguments),
292
346
  ]
293
347
 
294
348
  # Run the command
295
349
  result = subprocess.run(
296
- cmd,
297
- capture_output=True,
298
- text=True,
299
- timeout=30
350
+ cmd, capture_output=True, text=True, timeout=30, check=False
300
351
  )
301
352
 
302
353
  if result.returncode == 0:
@@ -338,10 +389,7 @@ class ExternalMCPServiceManager:
338
389
  them as tools in the gateway - they run as separate MCP servers.
339
390
  """
340
391
  # Create service instances
341
- services = [
342
- MCPVectorSearchService(),
343
- MCPBrowserService()
344
- ]
392
+ services = [MCPVectorSearchService(), MCPBrowserService()]
345
393
 
346
394
  # Initialize each service
347
395
  initialized_services = []
@@ -350,10 +398,11 @@ class ExternalMCPServiceManager:
350
398
  if await service.initialize():
351
399
  initialized_services.append(service)
352
400
  if self.logger:
353
- self.logger.info(f"Initialized external service: {service.service_name}")
354
- else:
355
- if self.logger:
356
- self.logger.warning(f"Failed to initialize: {service.service_name}")
401
+ self.logger.info(
402
+ f"Initialized external service: {service.service_name}"
403
+ )
404
+ elif self.logger:
405
+ self.logger.warning(f"Failed to initialize: {service.service_name}")
357
406
  except Exception as e:
358
407
  if self.logger:
359
408
  self.logger.error(f"Error initializing {service.service_name}: {e}")
@@ -370,7 +419,9 @@ class ExternalMCPServiceManager:
370
419
  all_tools.extend(service_def["tools"])
371
420
  return all_tools
372
421
 
373
- async def invoke_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
422
+ async def invoke_tool(
423
+ self, tool_name: str, arguments: Dict[str, Any]
424
+ ) -> Dict[str, Any]:
374
425
  """Invoke a tool from any registered external service."""
375
426
  # Find the service that handles this tool
376
427
  for service in self.services:
@@ -387,4 +438,6 @@ class ExternalMCPServiceManager:
387
438
  await service.shutdown()
388
439
  except Exception as e:
389
440
  if self.logger:
390
- self.logger.warning(f"Error shutting down {service.service_name}: {e}")
441
+ self.logger.warning(
442
+ f"Error shutting down {service.service_name}: {e}"
443
+ )
@@ -20,7 +20,7 @@ import asyncio
20
20
  import os
21
21
  import platform
22
22
  import sys
23
- from datetime import datetime
23
+ from datetime import datetime, timezone
24
24
  from typing import Any, Dict
25
25
 
26
26
  import psutil
@@ -86,7 +86,7 @@ class HealthCheckTool(BaseToolAdapter):
86
86
  Returns:
87
87
  Tool execution result with health check results
88
88
  """
89
- start_time = datetime.now()
89
+ start_time = datetime.now(timezone.utc)
90
90
 
91
91
  try:
92
92
  # Get parameters
@@ -98,7 +98,7 @@ class HealthCheckTool(BaseToolAdapter):
98
98
  results = await self._perform_health_checks(check_type, detailed, timeout)
99
99
 
100
100
  # Calculate execution time
101
- execution_time = (datetime.now() - start_time).total_seconds()
101
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
102
102
 
103
103
  # Update metrics
104
104
  self._update_metrics(True, execution_time)
@@ -115,7 +115,7 @@ class HealthCheckTool(BaseToolAdapter):
115
115
  )
116
116
 
117
117
  except Exception as e:
118
- execution_time = (datetime.now() - start_time).total_seconds()
118
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
119
119
  self._update_metrics(False, execution_time)
120
120
 
121
121
  return MCPToolResult(
@@ -130,7 +130,7 @@ class HealthCheckTool(BaseToolAdapter):
130
130
  ) -> Dict[str, Any]:
131
131
  """Perform the requested health checks."""
132
132
  results = {
133
- "timestamp": datetime.now().isoformat(),
133
+ "timestamp": datetime.now(timezone.utc).isoformat(),
134
134
  "check_type": check_type,
135
135
  "detailed": detailed,
136
136
  "overall_status": "unknown",
@@ -27,7 +27,7 @@ import json
27
27
  import platform
28
28
  import re
29
29
  import sys
30
- from datetime import datetime
30
+ from datetime import datetime, timezone
31
31
  from typing import Any, Dict, List, Optional
32
32
 
33
33
  from claude_mpm.services.mcp_gateway.core.interfaces import (
@@ -204,7 +204,7 @@ class HelloWorldTool(BaseToolAdapter):
204
204
  self.greeting_history: List[Dict[str, Any]] = []
205
205
  self.max_history_size = 100
206
206
 
207
- def validate_parameters(self, parameters: Dict[str, Any]) -> bool:
207
+ def validate_parameters(self, parameters: Dict[str, Any]) -> bool: # noqa: PLR0911
208
208
  """
209
209
  Enhanced parameter validation with detailed error messages.
210
210
 
@@ -305,7 +305,7 @@ class HelloWorldTool(BaseToolAdapter):
305
305
  Returns:
306
306
  Tool execution result with greeting
307
307
  """
308
- start_time = datetime.now()
308
+ start_time = datetime.now(timezone.utc)
309
309
 
310
310
  try:
311
311
  # Validate parameters
@@ -353,13 +353,13 @@ class HelloWorldTool(BaseToolAdapter):
353
353
  greeting = " ".join([greeting] * repeat)
354
354
 
355
355
  # Calculate execution time
356
- execution_time = (datetime.now() - start_time).total_seconds()
356
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
357
357
 
358
358
  # Build response data
359
359
  response_data = {
360
360
  "greeting": greeting,
361
361
  "mode": mode,
362
- "timestamp": datetime.now().isoformat(),
362
+ "timestamp": datetime.now(timezone.utc).isoformat(),
363
363
  }
364
364
 
365
365
  # Add metadata if requested
@@ -389,7 +389,7 @@ class HelloWorldTool(BaseToolAdapter):
389
389
  )
390
390
 
391
391
  except Exception as e:
392
- execution_time = (datetime.now() - start_time).total_seconds()
392
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
393
393
  self._update_metrics(False, execution_time)
394
394
  self._metrics["last_error"] = str(e)
395
395
 
@@ -409,11 +409,11 @@ class HelloWorldTool(BaseToolAdapter):
409
409
 
410
410
  async def _time_based_greeting(self) -> str:
411
411
  """Generate a greeting based on current time."""
412
- current_hour = datetime.now().hour
412
+ current_hour = datetime.now(timezone.utc).hour
413
413
 
414
414
  for (start, end), greeting in self.TIME_GREETINGS.items():
415
415
  if start <= current_hour < end:
416
- return f"{greeting}! It's {datetime.now().strftime('%I:%M %p')}."
416
+ return f"{greeting}! It's {datetime.now(timezone.utc).strftime('%I:%M %p')}."
417
417
 
418
418
  return "Hello! Time is a curious thing."
419
419
 
@@ -482,7 +482,7 @@ class HelloWorldTool(BaseToolAdapter):
482
482
  execution_time: Time taken to generate greeting
483
483
  """
484
484
  entry = {
485
- "timestamp": datetime.now().isoformat(),
485
+ "timestamp": datetime.now(timezone.utc).isoformat(),
486
486
  "mode": mode,
487
487
  "greeting": greeting[:100], # Truncate long greetings
488
488
  "execution_time": execution_time,