claude-mpm 3.1.1__py3-none-any.whl → 3.1.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 (47) hide show
  1. claude_mpm/__main__.py +27 -3
  2. claude_mpm/agents/INSTRUCTIONS.md +17 -2
  3. claude_mpm/agents/templates/test-integration-agent.md +34 -0
  4. claude_mpm/cli/README.md +109 -0
  5. claude_mpm/cli/__init__.py +172 -0
  6. claude_mpm/cli/commands/__init__.py +20 -0
  7. claude_mpm/cli/commands/agents.py +202 -0
  8. claude_mpm/cli/commands/info.py +94 -0
  9. claude_mpm/cli/commands/run.py +95 -0
  10. claude_mpm/cli/commands/tickets.py +70 -0
  11. claude_mpm/cli/commands/ui.py +79 -0
  12. claude_mpm/cli/parser.py +337 -0
  13. claude_mpm/cli/utils.py +190 -0
  14. claude_mpm/cli_enhancements.py +19 -0
  15. claude_mpm/core/agent_registry.py +4 -4
  16. claude_mpm/core/factories.py +1 -1
  17. claude_mpm/core/service_registry.py +1 -1
  18. claude_mpm/core/simple_runner.py +17 -27
  19. claude_mpm/hooks/claude_hooks/hook_handler.py +53 -4
  20. claude_mpm/models/__init__.py +106 -0
  21. claude_mpm/models/agent_definition.py +196 -0
  22. claude_mpm/models/common.py +41 -0
  23. claude_mpm/models/lifecycle.py +97 -0
  24. claude_mpm/models/modification.py +126 -0
  25. claude_mpm/models/persistence.py +57 -0
  26. claude_mpm/models/registry.py +91 -0
  27. claude_mpm/security/__init__.py +8 -0
  28. claude_mpm/security/bash_validator.py +393 -0
  29. claude_mpm/services/agent_lifecycle_manager.py +206 -94
  30. claude_mpm/services/agent_modification_tracker.py +27 -100
  31. claude_mpm/services/agent_persistence_service.py +74 -0
  32. claude_mpm/services/agent_registry.py +43 -82
  33. claude_mpm/services/agent_versioning.py +37 -0
  34. claude_mpm/services/{ticketing_service_original.py → legacy_ticketing_service.py} +16 -9
  35. claude_mpm/services/ticket_manager.py +5 -4
  36. claude_mpm/services/{ticket_manager_di.py → ticket_manager_dependency_injection.py} +39 -12
  37. claude_mpm/services/version_control/semantic_versioning.py +10 -9
  38. claude_mpm/utils/path_operations.py +20 -0
  39. {claude_mpm-3.1.1.dist-info → claude_mpm-3.1.3.dist-info}/METADATA +9 -1
  40. {claude_mpm-3.1.1.dist-info → claude_mpm-3.1.3.dist-info}/RECORD +45 -25
  41. claude_mpm/cli_main.py +0 -13
  42. claude_mpm/utils/import_migration_example.py +0 -80
  43. /claude_mpm/{cli.py → cli_old.py} +0 -0
  44. {claude_mpm-3.1.1.dist-info → claude_mpm-3.1.3.dist-info}/WHEEL +0 -0
  45. {claude_mpm-3.1.1.dist-info → claude_mpm-3.1.3.dist-info}/entry_points.txt +0 -0
  46. {claude_mpm-3.1.1.dist-info → claude_mpm-3.1.3.dist-info}/licenses/LICENSE +0 -0
  47. {claude_mpm-3.1.1.dist-info → claude_mpm-3.1.3.dist-info}/top_level.txt +0 -0
@@ -25,36 +25,35 @@ import hashlib
25
25
  import logging
26
26
  from pathlib import Path
27
27
  from typing import Dict, List, Optional, Set, Tuple, Any, Union
28
- from dataclasses import dataclass, field, asdict
28
+ from dataclasses import asdict
29
29
  from datetime import datetime
30
30
  from enum import Enum
31
31
 
32
- logger = logging.getLogger(__name__)
33
-
34
-
35
- # ============================================================================
36
- # Constants and Types
37
- # ============================================================================
38
-
39
- CORE_AGENT_TYPES = {
40
- 'engineer', 'architect', 'qa', 'security', 'documentation',
41
- 'ops', 'data', 'research', 'version_control'
42
- }
43
-
44
- SPECIALIZED_AGENT_TYPES = {
45
- 'pm_orchestrator', 'frontend', 'backend', 'devops', 'ml',
46
- 'database', 'api', 'mobile', 'cloud', 'testing'
47
- }
32
+ from claude_mpm.models.registry import AgentTier, AgentRegistryMetadata
33
+ from claude_mpm.models.common import (
34
+ CORE_AGENT_TYPES,
35
+ SPECIALIZED_AGENT_TYPES,
36
+ ALL_AGENT_TYPES,
37
+ AGENT_FILE_EXTENSIONS,
38
+ AGENT_IGNORE_PATTERNS
39
+ )
48
40
 
49
- ALL_AGENT_TYPES = CORE_AGENT_TYPES | SPECIALIZED_AGENT_TYPES
41
+ logger = logging.getLogger(__name__)
50
42
 
43
+ # Backward compatibility exports
44
+ # Export AgentRegistryMetadata as AgentMetadata for existing code
45
+ AgentMetadata = AgentRegistryMetadata
51
46
 
52
- class AgentTier(Enum):
53
- """Agent hierarchy tiers."""
54
- USER = "user"
55
- SYSTEM = "system"
47
+ __all__ = [
48
+ 'AgentTier',
49
+ 'AgentType',
50
+ 'AgentMetadata', # Alias for AgentRegistryMetadata
51
+ 'AgentRegistryMetadata',
52
+ 'AgentRegistry'
53
+ ]
56
54
 
57
55
 
56
+ # Keep local AgentType enum for internal classification logic
58
57
  class AgentType(Enum):
59
58
  """Agent classification types."""
60
59
  CORE = "core"
@@ -63,44 +62,6 @@ class AgentType(Enum):
63
62
  UNKNOWN = "unknown"
64
63
 
65
64
 
66
- # ============================================================================
67
- # Data Models
68
- # ============================================================================
69
-
70
- @dataclass
71
- class AgentMetadata:
72
- """Complete metadata for discovered agent."""
73
- name: str
74
- path: str
75
- tier: AgentTier
76
- agent_type: AgentType
77
- description: str = ""
78
- version: str = "0.0.0"
79
- dependencies: List[str] = field(default_factory=list)
80
- capabilities: List[str] = field(default_factory=list)
81
- created_at: float = field(default_factory=time.time)
82
- last_modified: float = field(default_factory=time.time)
83
- file_size: int = 0
84
- checksum: str = ""
85
- is_valid: bool = True
86
- validation_errors: List[str] = field(default_factory=list)
87
- metadata: Dict[str, Any] = field(default_factory=dict)
88
-
89
- def to_dict(self) -> Dict[str, Any]:
90
- """Convert to dictionary for serialization."""
91
- data = asdict(self)
92
- data['tier'] = self.tier.value
93
- data['agent_type'] = self.agent_type.value
94
- return data
95
-
96
- @classmethod
97
- def from_dict(cls, data: Dict[str, Any]) -> 'AgentMetadata':
98
- """Create from dictionary."""
99
- data['tier'] = AgentTier(data['tier'])
100
- data['agent_type'] = AgentType(data['agent_type'])
101
- return cls(**data)
102
-
103
-
104
65
  # ============================================================================
105
66
  # Main Registry Class
106
67
  # ============================================================================
@@ -119,7 +80,7 @@ class AgentRegistry:
119
80
  self.model_selector = model_selector
120
81
 
121
82
  # Registry storage
122
- self.registry: Dict[str, AgentMetadata] = {}
83
+ self.registry: Dict[str, AgentRegistryMetadata] = {}
123
84
  self.discovery_paths: List[Path] = []
124
85
 
125
86
  # Cache configuration
@@ -128,8 +89,8 @@ class AgentRegistry:
128
89
  self.cache_prefix = "agent_registry"
129
90
 
130
91
  # Discovery configuration
131
- self.file_extensions = {'.md', '.json', '.yaml', '.yml'}
132
- self.ignore_patterns = {'__pycache__', '.git', 'node_modules', '.pytest_cache'}
92
+ self.file_extensions = AGENT_FILE_EXTENSIONS
93
+ self.ignore_patterns = AGENT_IGNORE_PATTERNS
133
94
 
134
95
  # Statistics
135
96
  self.discovery_stats = {
@@ -169,7 +130,7 @@ class AgentRegistry:
169
130
  # Discovery Methods
170
131
  # ========================================================================
171
132
 
172
- def discover_agents(self, force_refresh: bool = False) -> Dict[str, AgentMetadata]:
133
+ def discover_agents(self, force_refresh: bool = False) -> Dict[str, AgentRegistryMetadata]:
173
134
  """
174
135
  Discover all available agents across configured paths.
175
136
 
@@ -269,7 +230,7 @@ class AgentRegistry:
269
230
 
270
231
  return name
271
232
 
272
- def _create_agent_metadata(self, file_path: Path, agent_name: str, tier: AgentTier) -> AgentMetadata:
233
+ def _create_agent_metadata(self, file_path: Path, agent_name: str, tier: AgentTier) -> AgentRegistryMetadata:
273
234
  """Create agent metadata from file."""
274
235
  # Get file stats
275
236
  stat = file_path.stat()
@@ -324,11 +285,11 @@ class AgentRegistry:
324
285
  except Exception as e:
325
286
  logger.warning(f"Failed to parse {file_path}: {e}")
326
287
 
327
- return AgentMetadata(
288
+ return AgentRegistryMetadata(
328
289
  name=agent_name,
329
290
  path=str(file_path),
330
291
  tier=tier,
331
- agent_type=agent_type,
292
+ agent_type=agent_type.value, # Convert enum to string
332
293
  description=description,
333
294
  version=version,
334
295
  capabilities=capabilities,
@@ -379,7 +340,7 @@ class AgentRegistry:
379
340
  def _apply_tier_precedence(self) -> None:
380
341
  """Apply tier precedence rules to discovered agents."""
381
342
  # Group agents by name
382
- agents_by_name: Dict[str, List[AgentMetadata]] = {}
343
+ agents_by_name: Dict[str, List[AgentRegistryMetadata]] = {}
383
344
 
384
345
  for agent in self.registry.values():
385
346
  if agent.name not in agents_by_name:
@@ -403,7 +364,7 @@ class AgentRegistry:
403
364
  # Validation Methods
404
365
  # ========================================================================
405
366
 
406
- def _validate_agent(self, metadata: AgentMetadata) -> bool:
367
+ def _validate_agent(self, metadata: AgentRegistryMetadata) -> bool:
407
368
  """Validate agent metadata and file."""
408
369
  errors = []
409
370
 
@@ -437,7 +398,7 @@ class AgentRegistry:
437
398
  # Cache Methods
438
399
  # ========================================================================
439
400
 
440
- def _get_cached_registry(self) -> Optional[Dict[str, AgentMetadata]]:
401
+ def _get_cached_registry(self) -> Optional[Dict[str, AgentRegistryMetadata]]:
441
402
  """Get registry from cache if available."""
442
403
  if not self.cache_service:
443
404
  return None
@@ -450,7 +411,7 @@ class AgentRegistry:
450
411
  # Deserialize metadata
451
412
  registry = {}
452
413
  for name, data in cached_data.items():
453
- registry[name] = AgentMetadata.from_dict(data)
414
+ registry[name] = AgentRegistryMetadata.from_dict(data)
454
415
  return registry
455
416
 
456
417
  except Exception as e:
@@ -491,7 +452,7 @@ class AgentRegistry:
491
452
  # Query Methods
492
453
  # ========================================================================
493
454
 
494
- def get_agent(self, name: str) -> Optional[AgentMetadata]:
455
+ def get_agent(self, name: str) -> Optional[AgentRegistryMetadata]:
495
456
  """Get metadata for a specific agent."""
496
457
  # Ensure registry is populated
497
458
  if not self.registry:
@@ -500,7 +461,7 @@ class AgentRegistry:
500
461
  return self.registry.get(name)
501
462
 
502
463
  def list_agents(self, tier: Optional[AgentTier] = None,
503
- agent_type: Optional[AgentType] = None) -> List[AgentMetadata]:
464
+ agent_type: Optional[str] = None) -> List[AgentRegistryMetadata]:
504
465
  """List agents with optional filtering."""
505
466
  # Ensure registry is populated
506
467
  if not self.registry:
@@ -524,19 +485,19 @@ class AgentRegistry:
524
485
 
525
486
  return sorted(self.registry.keys())
526
487
 
527
- def get_core_agents(self) -> List[AgentMetadata]:
488
+ def get_core_agents(self) -> List[AgentRegistryMetadata]:
528
489
  """Get all core framework agents."""
529
- return self.list_agents(agent_type=AgentType.CORE)
490
+ return self.list_agents(agent_type=AgentType.CORE.value)
530
491
 
531
- def get_specialized_agents(self) -> List[AgentMetadata]:
492
+ def get_specialized_agents(self) -> List[AgentRegistryMetadata]:
532
493
  """Get all specialized agents."""
533
- return self.list_agents(agent_type=AgentType.SPECIALIZED)
494
+ return self.list_agents(agent_type=AgentType.SPECIALIZED.value)
534
495
 
535
- def get_custom_agents(self) -> List[AgentMetadata]:
496
+ def get_custom_agents(self) -> List[AgentRegistryMetadata]:
536
497
  """Get all custom user-defined agents."""
537
- return self.list_agents(agent_type=AgentType.CUSTOM)
498
+ return self.list_agents(agent_type=AgentType.CUSTOM.value)
538
499
 
539
- def search_agents(self, query: str) -> List[AgentMetadata]:
500
+ def search_agents(self, query: str) -> List[AgentRegistryMetadata]:
540
501
  """Search agents by name or description."""
541
502
  if not self.registry:
542
503
  self.discover_agents()
@@ -579,7 +540,7 @@ class AgentRegistry:
579
540
 
580
541
  # Count by type
581
542
  for agent in self.registry.values():
582
- agent_type = agent.agent_type.value
543
+ agent_type = agent.agent_type # Already a string
583
544
  stats['agents_by_type'][agent_type] = stats['agents_by_type'].get(agent_type, 0) + 1
584
545
 
585
546
  # Validation stats
@@ -667,7 +628,7 @@ class AgentRegistry:
667
628
 
668
629
  # Import agents
669
630
  for name, agent_data in data.get('agents', {}).items():
670
- self.registry[name] = AgentMetadata.from_dict(agent_data)
631
+ self.registry[name] = AgentRegistryMetadata.from_dict(agent_data)
671
632
 
672
633
  # Cache imported registry
673
634
  if self.cache_enabled:
@@ -0,0 +1,37 @@
1
+ """
2
+ Agent Version Manager - Stub implementation for testing
3
+ """
4
+
5
+ class AgentVersionManager:
6
+ """Stub implementation of AgentVersionManager for integration testing."""
7
+
8
+ def __init__(self):
9
+ """Initialize version manager."""
10
+ pass
11
+
12
+ def get_next_version(self, current_version: str, change_type: str = "patch") -> str:
13
+ """Get next version number."""
14
+ parts = current_version.split(".")
15
+ if len(parts) != 3:
16
+ return "1.0.0"
17
+
18
+ major, minor, patch = map(int, parts)
19
+
20
+ if change_type == "major":
21
+ return f"{major + 1}.0.0"
22
+ elif change_type == "minor":
23
+ return f"{major}.{minor + 1}.0"
24
+ else: # patch
25
+ return f"{major}.{minor}.{patch + 1}"
26
+
27
+ def validate_version(self, version: str) -> bool:
28
+ """Validate version format."""
29
+ try:
30
+ parts = version.split(".")
31
+ if len(parts) != 3:
32
+ return False
33
+ for part in parts:
34
+ int(part)
35
+ return True
36
+ except:
37
+ return False
@@ -1,10 +1,13 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- Ticketing Service
4
- =================
3
+ Legacy Ticketing Service (DEPRECATED)
4
+ =====================================
5
5
 
6
- Core service that wraps ai-trackdown-pytools for simplified ticket management.
7
- Provides a clean interface for PM orchestration and agent ticket operations.
6
+ DEPRECATED: This is the original ticketing service implementation.
7
+ For new development, use TicketManager or TicketManagerDependencyInjection instead.
8
+
9
+ This service is kept for backward compatibility and reference purposes.
10
+ It wraps ai-trackdown-pytools for simplified ticket management.
8
11
 
9
12
  Key Features:
10
13
  - Singleton pattern for consistent ticket management
@@ -44,15 +47,19 @@ from datetime import datetime
44
47
  from pathlib import Path
45
48
  from typing import Any, Dict, List, Optional, Union
46
49
 
47
- # Import ai-trackdown-pytools
48
- try:
49
- from ai_trackdown_pytools import Task, Project
50
- from ai_trackdown_pytools.core.task import TaskManager
50
+ from claude_mpm.utils.imports import safe_import
51
+
52
+ # Import ai-trackdown-pytools using safe_import pattern
53
+ trackdown_imports = safe_import('ai_trackdown_pytools', None, ['Task', 'Project'])
54
+ TaskManager = safe_import('ai_trackdown_pytools.core.task', None, ['TaskManager'])
55
+
56
+ if trackdown_imports and TaskManager:
57
+ Task, Project = trackdown_imports
51
58
  AI_TRACKDOWN_AVAILABLE = True
52
59
  # Map to expected names
53
60
  Ticket = Task
54
61
  TicketManager = TaskManager
55
- except ImportError:
62
+ else:
56
63
  AI_TRACKDOWN_AVAILABLE = False
57
64
  # Define fallback classes for type hints
58
65
  class TicketStatus:
@@ -4,10 +4,11 @@ from pathlib import Path
4
4
  from typing import Optional, Dict, Any, List
5
5
  from datetime import datetime
6
6
 
7
- try:
8
- from ..core.logger import get_logger
9
- except ImportError:
10
- from core.logger import get_logger
7
+ from claude_mpm.utils.imports import safe_import
8
+
9
+ # Import logger using safe_import pattern
10
+ # Note: safe_import cannot handle relative imports as primary, use absolute import first
11
+ get_logger = safe_import('claude_mpm.core.logger', None, ['get_logger'])
11
12
 
12
13
 
13
14
  class TicketManager:
@@ -1,16 +1,39 @@
1
1
  """
2
- Enhanced Ticket Manager with Dependency Injection support.
2
+ Ticket Manager with Dependency Injection
3
+ ========================================
3
4
 
4
- This version demonstrates proper constructor injection and testability.
5
+ Modern implementation of the ticket manager service with full dependency injection support.
6
+ This is the recommended implementation for new development requiring ticket management.
7
+
8
+ Key Features:
9
+ - Constructor-based dependency injection
10
+ - Interface-based design for testability
11
+ - Easy mocking for unit tests
12
+ - Follows SOLID principles
13
+
14
+ Usage:
15
+ # With dependency injection container
16
+ ticket_manager = container.get(TicketManagerDependencyInjection)
17
+
18
+ # Manual instantiation with dependencies
19
+ ticket_manager = TicketManagerDependencyInjection(
20
+ config=config_service,
21
+ task_adapter=mock_adapter # For testing
22
+ )
23
+
24
+ This implementation supersedes the legacy_ticketing_service.py.
5
25
  """
6
26
 
7
27
  from pathlib import Path
8
28
  from typing import Optional, Dict, Any, List
9
29
  from datetime import datetime
10
30
 
11
- from ..core.injectable_service import InjectableService
12
- from ..core.config import Config
13
- from ..core.logger import get_logger
31
+ from claude_mpm.utils.imports import safe_import
32
+
33
+ # Import dependencies using safe_import pattern
34
+ InjectableService = safe_import('claude_mpm.core.injectable_service', None, ['InjectableService'])
35
+ Config = safe_import('claude_mpm.core.config', None, ['Config'])
36
+ get_logger = safe_import('claude_mpm.core.logger', None, ['get_logger'])
14
37
 
15
38
 
16
39
  class ITaskManagerAdapter:
@@ -40,10 +63,17 @@ class AITrackdownAdapter(ITaskManagerAdapter):
40
63
 
41
64
  def _init_task_manager(self):
42
65
  """Initialize ai-trackdown-pytools TaskManager."""
43
- try:
44
- from ai_trackdown_pytools.core.task import TaskManager
45
- from ai_trackdown_pytools import Config as TrackdownConfig, Project
66
+ # Import using safe_import pattern
67
+ TaskManager = safe_import('ai_trackdown_pytools.core.task', None, ['TaskManager'])
68
+ trackdown_imports = safe_import('ai_trackdown_pytools', None, ['Config', 'Project'])
69
+
70
+ if not TaskManager or not trackdown_imports:
71
+ self.logger.error("ai-trackdown-pytools not installed")
72
+ return None
46
73
 
74
+ TrackdownConfig, Project = trackdown_imports
75
+
76
+ try:
47
77
  # Ensure tickets directory exists
48
78
  tickets_dir = self.project_path / "tickets"
49
79
  if not tickets_dir.exists():
@@ -67,9 +97,6 @@ class AITrackdownAdapter(ITaskManagerAdapter):
67
97
  # Initialize task manager directly
68
98
  return TaskManager(self.project_path)
69
99
 
70
- except ImportError:
71
- self.logger.error("ai-trackdown-pytools not installed")
72
- return None
73
100
  except Exception as e:
74
101
  self.logger.error(f"Failed to initialize TaskManager: {e}")
75
102
  return None
@@ -93,7 +120,7 @@ class AITrackdownAdapter(ITaskManagerAdapter):
93
120
  return self._task_manager.load_task(task_id)
94
121
 
95
122
 
96
- class TicketManagerDI(InjectableService):
123
+ class TicketManagerDependencyInjection(InjectableService):
97
124
  """
98
125
  Enhanced Ticket Manager with Dependency Injection.
99
126
 
@@ -46,7 +46,10 @@ from dataclasses import dataclass, field
46
46
  from enum import Enum
47
47
  import logging
48
48
 
49
- from ...utils.config_manager import ConfigurationManager
49
+ from claude_mpm.utils.imports import safe_import
50
+
51
+ # Import dependencies using safe_import pattern
52
+ ConfigurationManager = safe_import('claude_mpm.utils.config_manager', None, ['ConfigurationManager'])
50
53
 
51
54
 
52
55
  class VersionBumpType(Enum):
@@ -367,14 +370,12 @@ class SemanticVersionManager:
367
370
 
368
371
  def _parse_pyproject_toml_version(self, file_path: Path) -> Optional[str]:
369
372
  """Parse version from pyproject.toml."""
370
- try:
371
- import tomllib
372
- except ImportError:
373
- try:
374
- import tomli as tomllib
375
- except ImportError:
376
- # Fallback to simple regex parsing
377
- return self._parse_toml_version_regex(file_path)
373
+ # Try to import tomllib (Python 3.11+) or tomli as fallback
374
+ tomllib = safe_import('tomllib', 'tomli')
375
+
376
+ if not tomllib:
377
+ # Fallback to simple regex parsing
378
+ return self._parse_toml_version_regex(file_path)
378
379
 
379
380
  try:
380
381
  with open(file_path, "rb") as f:
@@ -2,6 +2,26 @@
2
2
 
3
3
  This module provides a centralized PathOperations class for common path validation
4
4
  and file operations, reducing code duplication across the codebase.
5
+
6
+ ARCHITECTURAL DECISION: Separation of Concerns
7
+ ---------------------------------------------
8
+ This module (path_operations.py) and paths.py serve distinct purposes and should
9
+ remain separate:
10
+
11
+ 1. path_operations.py (this file):
12
+ - Provides safe file I/O operations (read, write, copy, delete)
13
+ - Handles file validation and permissions
14
+ - Implements error handling and recovery mechanisms
15
+ - Focus: File system operations with safety guarantees
16
+
17
+ 2. paths.py:
18
+ - Provides path discovery and resolution logic
19
+ - Handles framework/project directory structure navigation
20
+ - Implements caching for performance optimization
21
+ - Focus: Path resolution and directory structure
22
+
23
+ This separation follows the Single Responsibility Principle and makes the codebase
24
+ more maintainable by keeping distinct concerns in separate modules.
5
25
  """
6
26
 
7
27
  import os
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 3.1.1
3
+ Version: 3.1.3
4
4
  Summary: Claude Multi-agent Project Manager - Clean orchestration with ticket management
5
5
  Home-page: https://github.com/bobmatnyc/claude-mpm
6
6
  Author: Claude MPM Team
@@ -191,6 +191,14 @@ Claude MPM provides a modular framework for extending Claude's capabilities:
191
191
 
192
192
  ## Key Features
193
193
 
194
+ ### Security Features
195
+ - **File Access Restrictions**: Agents are restricted to their working directory
196
+ - **Bash Command Validation**: Comprehensive validation prevents writes outside project directory
197
+ - **Path Traversal Protection**: Blocks attempts to escape the working directory
198
+ - **Dangerous Command Blocking**: Prevents execution of sudo, rm -rf, and other risky commands
199
+ - **Security Audit Logging**: All file operations are logged for security monitoring
200
+ - See [Security Documentation](docs/SECURITY.md) for details
201
+
194
202
  ### Agent System
195
203
  - Specialized agents for different domains (Research, Engineer, etc.)
196
204
  - Dynamic agent discovery and registration