claude-mpm 3.9.8__py3-none-any.whl → 3.9.9__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 (44) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/base_agent.json +1 -1
  3. claude_mpm/cli/__init__.py +3 -1
  4. claude_mpm/cli/commands/__init__.py +3 -1
  5. claude_mpm/cli/commands/cleanup.py +21 -1
  6. claude_mpm/cli/commands/mcp.py +821 -0
  7. claude_mpm/cli/parser.py +148 -1
  8. claude_mpm/config/memory_guardian_config.py +325 -0
  9. claude_mpm/constants.py +13 -0
  10. claude_mpm/hooks/claude_hooks/hook_handler.py +76 -19
  11. claude_mpm/models/state_models.py +433 -0
  12. claude_mpm/services/communication/__init__.py +2 -2
  13. claude_mpm/services/communication/socketio.py +18 -16
  14. claude_mpm/services/infrastructure/__init__.py +4 -1
  15. claude_mpm/services/infrastructure/logging.py +3 -3
  16. claude_mpm/services/infrastructure/memory_guardian.py +770 -0
  17. claude_mpm/services/mcp_gateway/__init__.py +28 -12
  18. claude_mpm/services/mcp_gateway/main.py +326 -0
  19. claude_mpm/services/mcp_gateway/registry/__init__.py +6 -3
  20. claude_mpm/services/mcp_gateway/registry/service_registry.py +397 -0
  21. claude_mpm/services/mcp_gateway/registry/tool_registry.py +477 -0
  22. claude_mpm/services/mcp_gateway/server/__init__.py +9 -3
  23. claude_mpm/services/mcp_gateway/server/mcp_server.py +430 -0
  24. claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +444 -0
  25. claude_mpm/services/mcp_gateway/server/stdio_handler.py +373 -0
  26. claude_mpm/services/mcp_gateway/tools/__init__.py +16 -3
  27. claude_mpm/services/mcp_gateway/tools/base_adapter.py +497 -0
  28. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +729 -0
  29. claude_mpm/services/mcp_gateway/tools/hello_world.py +551 -0
  30. claude_mpm/utils/file_utils.py +293 -0
  31. claude_mpm/utils/platform_memory.py +524 -0
  32. claude_mpm/utils/subprocess_utils.py +305 -0
  33. {claude_mpm-3.9.8.dist-info → claude_mpm-3.9.9.dist-info}/METADATA +3 -1
  34. {claude_mpm-3.9.8.dist-info → claude_mpm-3.9.9.dist-info}/RECORD +39 -28
  35. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
  36. claude_mpm/agents/templates/.claude-mpm/memories/engineer_agent.md +0 -39
  37. claude_mpm/agents/templates/.claude-mpm/memories/qa_agent.md +0 -38
  38. claude_mpm/agents/templates/.claude-mpm/memories/research_agent.md +0 -39
  39. claude_mpm/agents/templates/.claude-mpm/memories/version_control_agent.md +0 -38
  40. /claude_mpm/agents/templates/{research_memory_efficient.json → backup/research_memory_efficient.json} +0 -0
  41. {claude_mpm-3.9.8.dist-info → claude_mpm-3.9.9.dist-info}/WHEEL +0 -0
  42. {claude_mpm-3.9.8.dist-info → claude_mpm-3.9.9.dist-info}/entry_points.txt +0 -0
  43. {claude_mpm-3.9.8.dist-info → claude_mpm-3.9.9.dist-info}/licenses/LICENSE +0 -0
  44. {claude_mpm-3.9.8.dist-info → claude_mpm-3.9.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,551 @@
1
+ """
2
+ Hello World Tool for MCP Gateway Testing and Validation
3
+ =========================================================
4
+
5
+ Comprehensive Hello World tool that demonstrates all MCP capabilities.
6
+ This tool serves as the primary validation for the MCP Gateway system.
7
+
8
+ Part of ISS-0036: Hello World Tool - Testing and Validation Tool
9
+
10
+ WHY: We need a comprehensive test tool that exercises all MCP features
11
+ including async operations, input validation, error handling, multi-language
12
+ support, and proper metrics tracking. This tool validates that our MCP
13
+ Gateway is functioning correctly.
14
+
15
+ DESIGN DECISIONS:
16
+ - Multiple greeting variations to test different parameter combinations
17
+ - Async operations to validate async tool support
18
+ - Comprehensive input validation with detailed error messages
19
+ - Multi-language support to test Unicode handling
20
+ - Time-based greetings to test dynamic responses
21
+ - Detailed metrics tracking for monitoring
22
+ - Rich metadata in responses for debugging
23
+ """
24
+
25
+ import asyncio
26
+ import platform
27
+ import sys
28
+ from datetime import datetime
29
+ from typing import Any, Dict, Optional, List
30
+ import json
31
+ import re
32
+
33
+ from claude_mpm.services.mcp_gateway.core.interfaces import (
34
+ MCPToolDefinition,
35
+ MCPToolInvocation,
36
+ MCPToolResult,
37
+ )
38
+ from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseToolAdapter
39
+
40
+
41
+ class HelloWorldTool(BaseToolAdapter):
42
+ """
43
+ Comprehensive Hello World tool for MCP Gateway testing.
44
+
45
+ This tool provides multiple greeting variations to thoroughly test
46
+ the MCP Gateway's tool execution capabilities.
47
+
48
+ Features:
49
+ - Simple greeting: Basic echo functionality
50
+ - Personalized greeting: Name-based customization
51
+ - Time-based greeting: Dynamic responses based on time of day
52
+ - Multi-language greeting: Unicode and internationalization support
53
+ - System info greeting: Integration with system information
54
+ - Async greeting: Tests async operation support
55
+ - Error scenarios: Validates error handling
56
+
57
+ TRADE-OFFS:
58
+ - Comprehensive testing vs simplicity: We chose comprehensive testing
59
+ to ensure all MCP features work correctly
60
+ - Multiple variations vs single greeting: Multiple variations allow
61
+ testing different parameter combinations and edge cases
62
+ """
63
+
64
+ # Supported languages for multi-language greetings
65
+ LANGUAGES = {
66
+ "english": "Hello",
67
+ "spanish": "Hola",
68
+ "french": "Bonjour",
69
+ "german": "Hallo",
70
+ "italian": "Ciao",
71
+ "portuguese": "Olá",
72
+ "russian": "Привет",
73
+ "japanese": "こんにちは",
74
+ "chinese": "你好",
75
+ "korean": "안녕하세요",
76
+ "arabic": "مرحبا",
77
+ "hindi": "नमस्ते",
78
+ "hebrew": "שלום",
79
+ "dutch": "Hallo",
80
+ "polish": "Cześć",
81
+ "swedish": "Hej",
82
+ "norwegian": "Hei",
83
+ "danish": "Hej",
84
+ "finnish": "Hei",
85
+ "greek": "Γειά σου",
86
+ "turkish": "Merhaba",
87
+ "thai": "สวัสดี",
88
+ "vietnamese": "Xin chào",
89
+ "indonesian": "Halo",
90
+ "malay": "Hai"
91
+ }
92
+
93
+ # Time-based greeting thresholds
94
+ TIME_GREETINGS = {
95
+ (0, 5): "Good night",
96
+ (5, 12): "Good morning",
97
+ (12, 17): "Good afternoon",
98
+ (17, 21): "Good evening",
99
+ (21, 24): "Good night"
100
+ }
101
+
102
+ def __init__(self):
103
+ """Initialize the Hello World tool with comprehensive schema."""
104
+ definition = MCPToolDefinition(
105
+ name="hello_world",
106
+ description=(
107
+ "A comprehensive Hello World tool for testing MCP Gateway functionality. "
108
+ "Provides multiple greeting variations including simple, personalized, "
109
+ "time-based, and multi-language greetings."
110
+ ),
111
+ input_schema={
112
+ "type": "object",
113
+ "properties": {
114
+ "mode": {
115
+ "type": "string",
116
+ "enum": [
117
+ "simple",
118
+ "personalized",
119
+ "time_based",
120
+ "multi_language",
121
+ "system_info",
122
+ "async_test",
123
+ "error_test"
124
+ ],
125
+ "description": "The greeting mode to use",
126
+ "default": "simple"
127
+ },
128
+ "name": {
129
+ "type": "string",
130
+ "description": "Name for personalized greeting (required for personalized mode)",
131
+ "minLength": 1,
132
+ "maxLength": 100
133
+ },
134
+ "language": {
135
+ "type": "string",
136
+ "description": "Language for multi-language greeting",
137
+ "enum": list(self.LANGUAGES.keys()),
138
+ "default": "english"
139
+ },
140
+ "delay_ms": {
141
+ "type": "number",
142
+ "description": "Delay in milliseconds for async test",
143
+ "minimum": 0,
144
+ "maximum": 5000,
145
+ "default": 1000
146
+ },
147
+ "error_type": {
148
+ "type": "string",
149
+ "enum": ["validation", "runtime", "timeout"],
150
+ "description": "Type of error to simulate for error_test mode",
151
+ "default": "validation"
152
+ },
153
+ "include_metadata": {
154
+ "type": "boolean",
155
+ "description": "Whether to include detailed metadata in response",
156
+ "default": True
157
+ },
158
+ "uppercase": {
159
+ "type": "boolean",
160
+ "description": "Convert greeting to uppercase",
161
+ "default": False
162
+ },
163
+ "repeat": {
164
+ "type": "number",
165
+ "description": "Number of times to repeat the greeting",
166
+ "minimum": 1,
167
+ "maximum": 10,
168
+ "default": 1
169
+ }
170
+ },
171
+ "required": ["mode"],
172
+ "additionalProperties": False
173
+ },
174
+ output_schema={
175
+ "type": "object",
176
+ "properties": {
177
+ "greeting": {
178
+ "type": "string",
179
+ "description": "The generated greeting message"
180
+ },
181
+ "mode": {
182
+ "type": "string",
183
+ "description": "The mode that was used"
184
+ },
185
+ "timestamp": {
186
+ "type": "string",
187
+ "description": "ISO timestamp when greeting was generated"
188
+ },
189
+ "metadata": {
190
+ "type": "object",
191
+ "description": "Additional metadata about the greeting",
192
+ "properties": {
193
+ "tool_version": {"type": "string"},
194
+ "execution_environment": {"type": "object"},
195
+ "parameters_used": {"type": "object"}
196
+ }
197
+ }
198
+ }
199
+ }
200
+ )
201
+ super().__init__(definition)
202
+
203
+ # Tool version for tracking
204
+ self.version = "1.0.0"
205
+
206
+ # Track greeting history for analytics
207
+ self.greeting_history: List[Dict[str, Any]] = []
208
+ self.max_history_size = 100
209
+
210
+ def validate_parameters(self, parameters: Dict[str, Any]) -> bool:
211
+ """
212
+ Enhanced parameter validation with detailed error messages.
213
+
214
+ Args:
215
+ parameters: Parameters to validate
216
+
217
+ Returns:
218
+ True if parameters are valid, False otherwise
219
+ """
220
+ # First do base validation
221
+ if not super().validate_parameters(parameters):
222
+ return False
223
+
224
+ mode = parameters.get("mode", "simple")
225
+
226
+ # Validate mode is in allowed enum
227
+ valid_modes = ["simple", "personalized", "time_based", "multi_language",
228
+ "system_info", "async_test", "error_test"]
229
+ if mode not in valid_modes:
230
+ self.log_error(f"Invalid mode: {mode}. Must be one of {valid_modes}")
231
+ return False
232
+
233
+ # Mode-specific validation
234
+ if mode == "personalized":
235
+ if "name" not in parameters or not parameters["name"]:
236
+ self.log_error("Personalized mode requires 'name' parameter")
237
+ return False
238
+
239
+ # Validate name format (alphanumeric and basic punctuation)
240
+ name = parameters["name"]
241
+ if not re.match(r"^[a-zA-Z0-9\s\-\'\.]+$", name):
242
+ self.log_error(f"Invalid name format: {name}")
243
+ return False
244
+
245
+ elif mode == "multi_language":
246
+ language = parameters.get("language", "english")
247
+ if language not in self.LANGUAGES:
248
+ self.log_error(f"Unsupported language: {language}")
249
+ return False
250
+
251
+ elif mode == "async_test":
252
+ delay = parameters.get("delay_ms", 1000)
253
+ if not isinstance(delay, (int, float)) or delay < 0 or delay > 5000:
254
+ self.log_error(f"Invalid delay_ms: {delay} (must be 0-5000)")
255
+ return False
256
+
257
+ elif mode == "error_test":
258
+ error_type = parameters.get("error_type", "validation")
259
+ if error_type not in ["validation", "runtime", "timeout"]:
260
+ self.log_error(f"Invalid error_type: {error_type}")
261
+ return False
262
+
263
+ # Validate common parameters
264
+ repeat = parameters.get("repeat", 1)
265
+ if not isinstance(repeat, int) or repeat < 1 or repeat > 10:
266
+ self.log_error(f"Invalid repeat value: {repeat} (must be 1-10)")
267
+ return False
268
+
269
+ return True
270
+
271
+ async def initialize(self) -> bool:
272
+ """
273
+ Initialize the Hello World tool.
274
+
275
+ Returns:
276
+ True if initialization successful
277
+ """
278
+ try:
279
+ self.log_info(f"Initializing Hello World Tool v{self.version}")
280
+
281
+ # Clear greeting history
282
+ self.greeting_history.clear()
283
+
284
+ # Mark as initialized
285
+ self._initialized = True
286
+
287
+ self.log_info("Hello World Tool initialized successfully")
288
+ return True
289
+
290
+ except Exception as e:
291
+ self.log_error(f"Failed to initialize Hello World Tool: {e}")
292
+ return False
293
+
294
+ async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
295
+ """
296
+ Invoke the Hello World tool with the specified mode.
297
+
298
+ Args:
299
+ invocation: Tool invocation request
300
+
301
+ Returns:
302
+ Tool execution result with greeting
303
+ """
304
+ start_time = datetime.now()
305
+
306
+ try:
307
+ # Validate parameters
308
+ if not self.validate_parameters(invocation.parameters):
309
+ return MCPToolResult(
310
+ success=False,
311
+ error="Parameter validation failed",
312
+ execution_time=0.0
313
+ )
314
+
315
+ # Extract parameters
316
+ mode = invocation.parameters.get("mode", "simple")
317
+ include_metadata = invocation.parameters.get("include_metadata", True)
318
+ uppercase = invocation.parameters.get("uppercase", False)
319
+ repeat = invocation.parameters.get("repeat", 1)
320
+
321
+ # Generate greeting based on mode
322
+ if mode == "simple":
323
+ greeting = await self._simple_greeting()
324
+ elif mode == "personalized":
325
+ name = invocation.parameters["name"]
326
+ greeting = await self._personalized_greeting(name)
327
+ elif mode == "time_based":
328
+ greeting = await self._time_based_greeting()
329
+ elif mode == "multi_language":
330
+ language = invocation.parameters.get("language", "english")
331
+ name = invocation.parameters.get("name")
332
+ greeting = await self._multi_language_greeting(language, name)
333
+ elif mode == "system_info":
334
+ greeting = await self._system_info_greeting()
335
+ elif mode == "async_test":
336
+ delay_ms = invocation.parameters.get("delay_ms", 1000)
337
+ greeting = await self._async_greeting(delay_ms)
338
+ elif mode == "error_test":
339
+ error_type = invocation.parameters.get("error_type", "validation")
340
+ return await self._error_test(error_type)
341
+ else:
342
+ greeting = f"Hello World! (Unknown mode: {mode})"
343
+
344
+ # Apply transformations
345
+ if uppercase:
346
+ greeting = greeting.upper()
347
+
348
+ if repeat > 1:
349
+ greeting = " ".join([greeting] * repeat)
350
+
351
+ # Calculate execution time
352
+ execution_time = (datetime.now() - start_time).total_seconds()
353
+
354
+ # Build response data
355
+ response_data = {
356
+ "greeting": greeting,
357
+ "mode": mode,
358
+ "timestamp": datetime.now().isoformat()
359
+ }
360
+
361
+ # Add metadata if requested
362
+ if include_metadata:
363
+ response_data["metadata"] = {
364
+ "tool_version": self.version,
365
+ "execution_environment": {
366
+ "platform": platform.platform(),
367
+ "python_version": sys.version,
368
+ "processor": platform.processor() or "unknown"
369
+ },
370
+ "parameters_used": invocation.parameters,
371
+ "execution_time_ms": execution_time * 1000
372
+ }
373
+
374
+ # Track in history
375
+ self._add_to_history(mode, greeting, execution_time)
376
+
377
+ # Update metrics
378
+ self._update_metrics(True, execution_time)
379
+
380
+ return MCPToolResult(
381
+ success=True,
382
+ data=response_data,
383
+ execution_time=execution_time,
384
+ metadata={
385
+ "tool": "hello_world",
386
+ "version": self.version,
387
+ "mode": mode
388
+ }
389
+ )
390
+
391
+ except Exception as e:
392
+ execution_time = (datetime.now() - start_time).total_seconds()
393
+ self._update_metrics(False, execution_time)
394
+ self._metrics["last_error"] = str(e)
395
+
396
+ return MCPToolResult(
397
+ success=False,
398
+ error=f"Hello World tool failed: {str(e)}",
399
+ execution_time=execution_time
400
+ )
401
+
402
+ async def _simple_greeting(self) -> str:
403
+ """Generate a simple greeting."""
404
+ return "Hello World!"
405
+
406
+ async def _personalized_greeting(self, name: str) -> str:
407
+ """Generate a personalized greeting."""
408
+ return f"Hello, {name}! Welcome to the MCP Gateway."
409
+
410
+ async def _time_based_greeting(self) -> str:
411
+ """Generate a greeting based on current time."""
412
+ current_hour = datetime.now().hour
413
+
414
+ for (start, end), greeting in self.TIME_GREETINGS.items():
415
+ if start <= current_hour < end:
416
+ return f"{greeting}! It's {datetime.now().strftime('%I:%M %p')}."
417
+
418
+ return "Hello! Time is a curious thing."
419
+
420
+ async def _multi_language_greeting(self, language: str, name: Optional[str] = None) -> str:
421
+ """Generate a greeting in the specified language."""
422
+ greeting_word = self.LANGUAGES.get(language, "Hello")
423
+
424
+ if name:
425
+ # Add name if provided (works for most languages)
426
+ return f"{greeting_word}, {name}!"
427
+ else:
428
+ return f"{greeting_word}, World!"
429
+
430
+ async def _system_info_greeting(self) -> str:
431
+ """Generate a greeting with system information."""
432
+ system = platform.system()
433
+ node = platform.node()
434
+ py_version = platform.python_version()
435
+
436
+ return (
437
+ f"Hello from {system} on {node}! "
438
+ f"Running Python {py_version} with MCP Gateway."
439
+ )
440
+
441
+ async def _async_greeting(self, delay_ms: int) -> str:
442
+ """Generate a greeting after an async delay."""
443
+ self.log_info(f"Starting async greeting with {delay_ms}ms delay")
444
+
445
+ # Convert milliseconds to seconds for asyncio.sleep
446
+ delay_seconds = delay_ms / 1000.0
447
+ await asyncio.sleep(delay_seconds)
448
+
449
+ return f"Hello World! (after {delay_ms}ms async delay)"
450
+
451
+ async def _error_test(self, error_type: str) -> MCPToolResult:
452
+ """Simulate various error conditions for testing."""
453
+ if error_type == "validation":
454
+ return MCPToolResult(
455
+ success=False,
456
+ error="Simulated validation error: Invalid input parameters",
457
+ execution_time=0.001
458
+ )
459
+ elif error_type == "runtime":
460
+ # Simulate a runtime error
461
+ raise RuntimeError("Simulated runtime error during greeting generation")
462
+ elif error_type == "timeout":
463
+ # Simulate a timeout by sleeping longer than reasonable
464
+ await asyncio.sleep(10) # This would typically trigger a timeout
465
+ return MCPToolResult(
466
+ success=False,
467
+ error="Operation timed out",
468
+ execution_time=10.0
469
+ )
470
+ else:
471
+ return MCPToolResult(
472
+ success=False,
473
+ error=f"Unknown error type: {error_type}",
474
+ execution_time=0.001
475
+ )
476
+
477
+ def _add_to_history(self, mode: str, greeting: str, execution_time: float) -> None:
478
+ """
479
+ Add greeting to history for analytics.
480
+
481
+ Args:
482
+ mode: Greeting mode used
483
+ greeting: Generated greeting
484
+ execution_time: Time taken to generate greeting
485
+ """
486
+ entry = {
487
+ "timestamp": datetime.now().isoformat(),
488
+ "mode": mode,
489
+ "greeting": greeting[:100], # Truncate long greetings
490
+ "execution_time": execution_time
491
+ }
492
+
493
+ self.greeting_history.append(entry)
494
+
495
+ # Maintain history size limit
496
+ if len(self.greeting_history) > self.max_history_size:
497
+ self.greeting_history.pop(0)
498
+
499
+ def get_analytics(self) -> Dict[str, Any]:
500
+ """
501
+ Get analytics about tool usage.
502
+
503
+ Returns:
504
+ Analytics dictionary with usage statistics
505
+ """
506
+ if not self.greeting_history:
507
+ return {
508
+ "total_greetings": 0,
509
+ "modes_used": {},
510
+ "average_execution_time": 0.0,
511
+ "last_greeting": None
512
+ }
513
+
514
+ # Calculate mode usage
515
+ modes_used = {}
516
+ total_time = 0.0
517
+
518
+ for entry in self.greeting_history:
519
+ mode = entry["mode"]
520
+ modes_used[mode] = modes_used.get(mode, 0) + 1
521
+ total_time += entry["execution_time"]
522
+
523
+ return {
524
+ "total_greetings": len(self.greeting_history),
525
+ "modes_used": modes_used,
526
+ "average_execution_time": total_time / len(self.greeting_history),
527
+ "last_greeting": self.greeting_history[-1] if self.greeting_history else None,
528
+ "metrics": self.get_metrics()
529
+ }
530
+
531
+ async def shutdown(self) -> None:
532
+ """
533
+ Shutdown the Hello World tool and clean up resources.
534
+ """
535
+ try:
536
+ self.log_info(f"Shutting down Hello World Tool v{self.version}")
537
+
538
+ # Log final analytics
539
+ analytics = self.get_analytics()
540
+ self.log_info(f"Final analytics: {json.dumps(analytics, indent=2)}")
541
+
542
+ # Clear history
543
+ self.greeting_history.clear()
544
+
545
+ # Mark as not initialized
546
+ self._initialized = False
547
+
548
+ self.log_info("Hello World Tool shutdown complete")
549
+
550
+ except Exception as e:
551
+ self.log_error(f"Error during Hello World Tool shutdown: {e}")