claude-mpm 3.9.11__py3-none-any.whl → 4.0.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 (419) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +1 -1
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +79 -51
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +20 -20
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +140 -905
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1156
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +71 -73
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +35 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  298. claude_mpm/services/mcp_gateway/main.py +287 -137
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +19 -533
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +2 -2
  358. claude_mpm/storage/state_storage.py +177 -181
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +27 -1
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/cli/commands/run_guarded.py +0 -511
  385. claude_mpm/config/memory_guardian_config.py +0 -325
  386. claude_mpm/config/memory_guardian_yaml.py +0 -335
  387. claude_mpm/core/config_paths.py +0 -150
  388. claude_mpm/core/memory_aware_runner.py +0 -353
  389. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  390. claude_mpm/deployment_paths.py +0 -261
  391. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  392. claude_mpm/models/state_models.py +0 -433
  393. claude_mpm/services/agent/__init__.py +0 -24
  394. claude_mpm/services/agent/deployment.py +0 -2548
  395. claude_mpm/services/agent/management.py +0 -598
  396. claude_mpm/services/agent/registry.py +0 -813
  397. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  398. claude_mpm/services/communication/socketio.py +0 -1935
  399. claude_mpm/services/communication/websocket.py +0 -479
  400. claude_mpm/services/framework_claude_md_generator.py +0 -624
  401. claude_mpm/services/health_monitor.py +0 -893
  402. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  403. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  404. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  405. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  406. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  407. claude_mpm/services/infrastructure/state_manager.py +0 -774
  408. claude_mpm/services/mcp_gateway/manager.py +0 -334
  409. claude_mpm/services/optimized_hook_service.py +0 -542
  410. claude_mpm/services/project_analyzer.py +0 -864
  411. claude_mpm/services/project_registry.py +0 -608
  412. claude_mpm/services/standalone_socketio_server.py +0 -1300
  413. claude_mpm/services/ticket_manager_di.py +0 -318
  414. claude_mpm/services/ticketing_service_original.py +0 -510
  415. claude_mpm/utils/paths.py +0 -395
  416. claude_mpm/utils/platform_memory.py +0 -524
  417. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  418. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  419. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,652 @@
1
+ """
2
+ MCP Tool Adapters for aitrackdown Ticket Management
3
+ ====================================================
4
+
5
+ Provides MCP tool wrappers for common aitrackdown operations, enabling
6
+ ticket management through Claude Desktop's MCP interface.
7
+
8
+ WHY: These tools allow Claude Desktop to interact with aitrackdown for
9
+ ticket management without requiring direct CLI access, providing a
10
+ seamless integration experience.
11
+
12
+ DESIGN DECISIONS:
13
+ - Thin wrappers that delegate to aitrackdown CLI for actual operations
14
+ - Focus on the most common operations that benefit from Claude integration
15
+ - Structured responses for better error handling and user feedback
16
+ - Async execution to avoid blocking the MCP gateway
17
+ """
18
+
19
+ import asyncio
20
+ import json
21
+ import subprocess
22
+ from datetime import datetime
23
+ from typing import Any, Dict, List, Optional
24
+
25
+ from claude_mpm.services.mcp_gateway.core.interfaces import (
26
+ MCPToolDefinition,
27
+ MCPToolInvocation,
28
+ MCPToolResult,
29
+ )
30
+ from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseToolAdapter
31
+
32
+
33
+ class TicketCreateTool(BaseToolAdapter):
34
+ """
35
+ Create new tickets using aitrackdown.
36
+
37
+ WHY: Creating tickets is the most fundamental operation for tracking work items.
38
+ This tool provides a simple interface for creating tasks, issues, and epics.
39
+ """
40
+
41
+ def __init__(self):
42
+ """Initialize the ticket create tool."""
43
+ definition = MCPToolDefinition(
44
+ name="ticket_create",
45
+ description="Create a new ticket (task, issue, or epic) using aitrackdown",
46
+ input_schema={
47
+ "type": "object",
48
+ "properties": {
49
+ "type": {
50
+ "type": "string",
51
+ "enum": ["task", "issue", "epic"],
52
+ "description": "Type of ticket to create",
53
+ },
54
+ "title": {"type": "string", "description": "Title of the ticket"},
55
+ "description": {
56
+ "type": "string",
57
+ "description": "Detailed description of the ticket",
58
+ },
59
+ "priority": {
60
+ "type": "string",
61
+ "enum": ["low", "medium", "high", "critical"],
62
+ "description": "Priority level",
63
+ "default": "medium",
64
+ },
65
+ "tags": {
66
+ "type": "array",
67
+ "items": {"type": "string"},
68
+ "description": "Tags to associate with the ticket",
69
+ },
70
+ "parent_epic": {
71
+ "type": "string",
72
+ "description": "Parent epic ID (for issues)",
73
+ },
74
+ "parent_issue": {
75
+ "type": "string",
76
+ "description": "Parent issue ID (for tasks)",
77
+ },
78
+ },
79
+ "required": ["type", "title"],
80
+ },
81
+ )
82
+ super().__init__(definition)
83
+
84
+ async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
85
+ """
86
+ Create a ticket using aitrackdown CLI.
87
+
88
+ Args:
89
+ invocation: Tool invocation request
90
+
91
+ Returns:
92
+ Tool execution result with created ticket ID
93
+ """
94
+ start_time = datetime.now()
95
+
96
+ try:
97
+ params = invocation.parameters
98
+
99
+ # Build aitrackdown command
100
+ cmd = ["aitrackdown", "create", params["type"], params["title"]]
101
+
102
+ # Add optional parameters
103
+ if "description" in params:
104
+ cmd.extend(["--description", params["description"]])
105
+
106
+ if "priority" in params:
107
+ cmd.extend(["--priority", params["priority"]])
108
+
109
+ if "tags" in params and params["tags"]:
110
+ # aitrackdown uses --tag for tags (singular)
111
+ for tag in params["tags"]:
112
+ cmd.extend(["--tag", tag])
113
+
114
+ # For tasks, use --issue to associate with parent issue
115
+ if params["type"] == "task" and "parent_issue" in params:
116
+ cmd.extend(["--issue", params["parent_issue"]])
117
+
118
+ # Execute command asynchronously
119
+ process = await asyncio.create_subprocess_exec(
120
+ *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
121
+ )
122
+
123
+ stdout, stderr = await process.communicate()
124
+
125
+ execution_time = (datetime.now() - start_time).total_seconds()
126
+
127
+ if process.returncode == 0:
128
+ # Parse ticket ID from output
129
+ output = stdout.decode().strip()
130
+ # aitrackdown typically returns "Created ticket: TSK-XXXX" or similar
131
+ ticket_id = None
132
+ for line in output.split("\n"):
133
+ if "TSK-" in line or "ISS-" in line or "EP-" in line:
134
+ # Extract ticket ID
135
+ import re
136
+
137
+ match = re.search(r"(TSK|ISS|EP)-\d+", line)
138
+ if match:
139
+ ticket_id = match.group(0)
140
+ break
141
+
142
+ self._update_metrics(True, execution_time)
143
+
144
+ return MCPToolResult(
145
+ success=True,
146
+ data={
147
+ "ticket_id": ticket_id or "Unknown",
148
+ "type": params["type"],
149
+ "title": params["title"],
150
+ "message": output,
151
+ },
152
+ execution_time=execution_time,
153
+ metadata={"tool": "ticket_create", "operation": "create"},
154
+ )
155
+ else:
156
+ error_msg = stderr.decode() if stderr else stdout.decode()
157
+ self._update_metrics(False, execution_time)
158
+
159
+ return MCPToolResult(
160
+ success=False,
161
+ error=f"Failed to create ticket: {error_msg}",
162
+ execution_time=execution_time,
163
+ )
164
+
165
+ except Exception as e:
166
+ execution_time = (datetime.now() - start_time).total_seconds()
167
+ self._update_metrics(False, execution_time)
168
+
169
+ return MCPToolResult(
170
+ success=False,
171
+ error=f"Ticket creation failed: {str(e)}",
172
+ execution_time=execution_time,
173
+ )
174
+
175
+
176
+ class TicketListTool(BaseToolAdapter):
177
+ """
178
+ List tickets with optional filters using aitrackdown status command.
179
+
180
+ WHY: Users need to review and browse existing tickets. This tool provides
181
+ a quick way to list recent tickets with filtering capabilities.
182
+ """
183
+
184
+ def __init__(self):
185
+ """Initialize the ticket list tool."""
186
+ definition = MCPToolDefinition(
187
+ name="ticket_list",
188
+ description="List tickets with optional filters using status command",
189
+ input_schema={
190
+ "type": "object",
191
+ "properties": {
192
+ "limit": {
193
+ "type": "number",
194
+ "description": "Maximum number of tickets to return",
195
+ "default": 10,
196
+ },
197
+ "type": {
198
+ "type": "string",
199
+ "enum": ["all", "task", "issue", "epic"],
200
+ "description": "Filter by ticket type",
201
+ "default": "all",
202
+ },
203
+ "status": {
204
+ "type": "string",
205
+ "enum": [
206
+ "all",
207
+ "open",
208
+ "in_progress",
209
+ "done",
210
+ "closed",
211
+ "blocked",
212
+ ],
213
+ "description": "Filter by status",
214
+ "default": "all",
215
+ },
216
+ "priority": {
217
+ "type": "string",
218
+ "enum": ["all", "low", "medium", "high", "critical"],
219
+ "description": "Filter by priority",
220
+ "default": "all",
221
+ },
222
+ },
223
+ "required": [],
224
+ },
225
+ )
226
+ super().__init__(definition)
227
+
228
+ async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
229
+ """
230
+ List tickets using aitrackdown CLI.
231
+
232
+ Args:
233
+ invocation: Tool invocation request
234
+
235
+ Returns:
236
+ Tool execution result with list of tickets
237
+ """
238
+ start_time = datetime.now()
239
+
240
+ try:
241
+ params = invocation.parameters
242
+ limit = params.get("limit", 10)
243
+
244
+ # Build aitrackdown command - use status tasks for listing
245
+ cmd = ["aitrackdown", "status", "tasks", "--limit", str(limit)]
246
+
247
+ # Add filters
248
+ if params.get("status") and params["status"] != "all":
249
+ cmd.extend(["--status", params["status"]])
250
+
251
+ # Execute command asynchronously
252
+ process = await asyncio.create_subprocess_exec(
253
+ *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
254
+ )
255
+
256
+ stdout, stderr = await process.communicate()
257
+
258
+ execution_time = (datetime.now() - start_time).total_seconds()
259
+
260
+ if process.returncode == 0:
261
+ try:
262
+ # Try to parse JSON output
263
+ tickets = json.loads(stdout.decode())
264
+ except json.JSONDecodeError:
265
+ # Fallback to text parsing if JSON fails
266
+ output = stdout.decode().strip()
267
+ tickets = {"raw_output": output, "count": output.count("\n") + 1}
268
+
269
+ self._update_metrics(True, execution_time)
270
+
271
+ return MCPToolResult(
272
+ success=True,
273
+ data=tickets,
274
+ execution_time=execution_time,
275
+ metadata={
276
+ "tool": "ticket_list",
277
+ "operation": "list",
278
+ "count": len(tickets) if isinstance(tickets, list) else 1,
279
+ },
280
+ )
281
+ else:
282
+ error_msg = stderr.decode() if stderr else stdout.decode()
283
+ self._update_metrics(False, execution_time)
284
+
285
+ return MCPToolResult(
286
+ success=False,
287
+ error=f"Failed to list tickets: {error_msg}",
288
+ execution_time=execution_time,
289
+ )
290
+
291
+ except Exception as e:
292
+ execution_time = (datetime.now() - start_time).total_seconds()
293
+ self._update_metrics(False, execution_time)
294
+
295
+ return MCPToolResult(
296
+ success=False,
297
+ error=f"Ticket listing failed: {str(e)}",
298
+ execution_time=execution_time,
299
+ )
300
+
301
+
302
+ class TicketUpdateTool(BaseToolAdapter):
303
+ """
304
+ Update ticket status or priority.
305
+
306
+ WHY: Tickets need to be updated as work progresses. This tool provides
307
+ a simple interface for updating ticket status and priority.
308
+ """
309
+
310
+ def __init__(self):
311
+ """Initialize the ticket update tool."""
312
+ definition = MCPToolDefinition(
313
+ name="ticket_update",
314
+ description="Update a ticket's status or priority",
315
+ input_schema={
316
+ "type": "object",
317
+ "properties": {
318
+ "ticket_id": {
319
+ "type": "string",
320
+ "description": "Ticket ID to update (e.g., TSK-0001)",
321
+ },
322
+ "status": {
323
+ "type": "string",
324
+ "enum": [
325
+ "open",
326
+ "in-progress",
327
+ "ready",
328
+ "tested",
329
+ "done",
330
+ "waiting",
331
+ ],
332
+ "description": "New status for the ticket (workflow state)",
333
+ },
334
+ "priority": {
335
+ "type": "string",
336
+ "enum": ["low", "medium", "high", "critical"],
337
+ "description": "New priority for the ticket",
338
+ },
339
+ "comment": {
340
+ "type": "string",
341
+ "description": "Optional comment for the update",
342
+ },
343
+ },
344
+ "required": ["ticket_id"],
345
+ },
346
+ )
347
+ super().__init__(definition)
348
+
349
+ async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
350
+ """
351
+ Update a ticket using aitrackdown CLI.
352
+
353
+ Args:
354
+ invocation: Tool invocation request
355
+
356
+ Returns:
357
+ Tool execution result
358
+ """
359
+ start_time = datetime.now()
360
+
361
+ try:
362
+ params = invocation.parameters
363
+ ticket_id = params["ticket_id"]
364
+
365
+ # Determine which update to perform
366
+ if "status" in params:
367
+ # Use transition command for status updates
368
+ cmd = ["aitrackdown", "transition", ticket_id, params["status"]]
369
+
370
+ if "comment" in params:
371
+ cmd.extend(["--comment", params["comment"]])
372
+ elif "priority" in params:
373
+ # For priority updates, we might need to use edit or transition
374
+ # aitrackdown doesn't have a direct update command, so use transition
375
+ cmd = ["aitrackdown", "transition", ticket_id, "open"]
376
+ cmd.extend(["--comment", f"Priority changed to {params['priority']}"])
377
+
378
+ if "comment" in params:
379
+ cmd.extend(["--comment", params["comment"]])
380
+ else:
381
+ return MCPToolResult(
382
+ success=False,
383
+ error="No update fields provided (status or priority required)",
384
+ execution_time=0.0,
385
+ )
386
+
387
+ # Execute command asynchronously
388
+ process = await asyncio.create_subprocess_exec(
389
+ *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
390
+ )
391
+
392
+ stdout, stderr = await process.communicate()
393
+
394
+ execution_time = (datetime.now() - start_time).total_seconds()
395
+
396
+ if process.returncode == 0:
397
+ self._update_metrics(True, execution_time)
398
+
399
+ return MCPToolResult(
400
+ success=True,
401
+ data={
402
+ "ticket_id": ticket_id,
403
+ "updated_fields": [
404
+ k for k in ["status", "priority"] if k in params
405
+ ],
406
+ "message": stdout.decode().strip(),
407
+ },
408
+ execution_time=execution_time,
409
+ metadata={"tool": "ticket_update", "operation": "update"},
410
+ )
411
+ else:
412
+ error_msg = stderr.decode() if stderr else stdout.decode()
413
+ self._update_metrics(False, execution_time)
414
+
415
+ return MCPToolResult(
416
+ success=False,
417
+ error=f"Failed to update ticket: {error_msg}",
418
+ execution_time=execution_time,
419
+ )
420
+
421
+ except Exception as e:
422
+ execution_time = (datetime.now() - start_time).total_seconds()
423
+ self._update_metrics(False, execution_time)
424
+
425
+ return MCPToolResult(
426
+ success=False,
427
+ error=f"Ticket update failed: {str(e)}",
428
+ execution_time=execution_time,
429
+ )
430
+
431
+
432
+ class TicketViewTool(BaseToolAdapter):
433
+ """
434
+ View detailed ticket information.
435
+
436
+ WHY: Users need to see full ticket details including description, metadata,
437
+ and all associated information for understanding context and status.
438
+ """
439
+
440
+ def __init__(self):
441
+ """Initialize the ticket view tool."""
442
+ definition = MCPToolDefinition(
443
+ name="ticket_view",
444
+ description="View detailed information about a specific ticket",
445
+ input_schema={
446
+ "type": "object",
447
+ "properties": {
448
+ "ticket_id": {
449
+ "type": "string",
450
+ "description": "Ticket ID to view (e.g., TSK-0001)",
451
+ },
452
+ "format": {
453
+ "type": "string",
454
+ "enum": ["json", "text"],
455
+ "description": "Output format",
456
+ "default": "json",
457
+ },
458
+ },
459
+ "required": ["ticket_id"],
460
+ },
461
+ )
462
+ super().__init__(definition)
463
+
464
+ async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
465
+ """
466
+ View a ticket using aitrackdown CLI.
467
+
468
+ Args:
469
+ invocation: Tool invocation request
470
+
471
+ Returns:
472
+ Tool execution result with ticket details
473
+ """
474
+ start_time = datetime.now()
475
+
476
+ try:
477
+ params = invocation.parameters
478
+ ticket_id = params["ticket_id"]
479
+ format_type = params.get("format", "json")
480
+
481
+ # Build aitrackdown command - use show for viewing
482
+ cmd = ["aitrackdown", "show", ticket_id]
483
+
484
+ # Execute command asynchronously
485
+ process = await asyncio.create_subprocess_exec(
486
+ *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
487
+ )
488
+
489
+ stdout, stderr = await process.communicate()
490
+
491
+ execution_time = (datetime.now() - start_time).total_seconds()
492
+
493
+ if process.returncode == 0:
494
+ output = stdout.decode().strip()
495
+
496
+ if format_type == "json":
497
+ try:
498
+ ticket_data = json.loads(output)
499
+ except json.JSONDecodeError:
500
+ ticket_data = {"raw_output": output}
501
+ else:
502
+ ticket_data = {"raw_output": output}
503
+
504
+ self._update_metrics(True, execution_time)
505
+
506
+ return MCPToolResult(
507
+ success=True,
508
+ data=ticket_data,
509
+ execution_time=execution_time,
510
+ metadata={
511
+ "tool": "ticket_view",
512
+ "operation": "view",
513
+ "ticket_id": ticket_id,
514
+ },
515
+ )
516
+ else:
517
+ error_msg = stderr.decode() if stderr else stdout.decode()
518
+ self._update_metrics(False, execution_time)
519
+
520
+ return MCPToolResult(
521
+ success=False,
522
+ error=f"Failed to view ticket: {error_msg}",
523
+ execution_time=execution_time,
524
+ )
525
+
526
+ except Exception as e:
527
+ execution_time = (datetime.now() - start_time).total_seconds()
528
+ self._update_metrics(False, execution_time)
529
+
530
+ return MCPToolResult(
531
+ success=False,
532
+ error=f"Ticket view failed: {str(e)}",
533
+ execution_time=execution_time,
534
+ )
535
+
536
+
537
+ class TicketSearchTool(BaseToolAdapter):
538
+ """
539
+ Search tickets by keywords.
540
+
541
+ WHY: Users need to find specific tickets based on content, tags, or other criteria.
542
+ This tool provides keyword search across ticket titles and descriptions.
543
+ """
544
+
545
+ def __init__(self):
546
+ """Initialize the ticket search tool."""
547
+ definition = MCPToolDefinition(
548
+ name="ticket_search",
549
+ description="Search tickets by keywords in title or description",
550
+ input_schema={
551
+ "type": "object",
552
+ "properties": {
553
+ "query": {"type": "string", "description": "Search query keywords"},
554
+ "limit": {
555
+ "type": "number",
556
+ "description": "Maximum number of results",
557
+ "default": 10,
558
+ },
559
+ "type": {
560
+ "type": "string",
561
+ "enum": ["all", "task", "issue", "epic"],
562
+ "description": "Filter by ticket type",
563
+ "default": "all",
564
+ },
565
+ },
566
+ "required": ["query"],
567
+ },
568
+ )
569
+ super().__init__(definition)
570
+
571
+ async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
572
+ """
573
+ Search tickets using aitrackdown CLI.
574
+
575
+ Args:
576
+ invocation: Tool invocation request
577
+
578
+ Returns:
579
+ Tool execution result with matching tickets
580
+ """
581
+ start_time = datetime.now()
582
+
583
+ try:
584
+ params = invocation.parameters
585
+ query = params["query"]
586
+ limit = params.get("limit", 10)
587
+
588
+ # Build aitrackdown command - use search tasks
589
+ cmd = ["aitrackdown", "search", "tasks", query, "--limit", str(limit)]
590
+
591
+ if params.get("type") and params["type"] != "all":
592
+ cmd.extend(["--type", params["type"]])
593
+
594
+ # Execute command asynchronously
595
+ process = await asyncio.create_subprocess_exec(
596
+ *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
597
+ )
598
+
599
+ stdout, stderr = await process.communicate()
600
+
601
+ execution_time = (datetime.now() - start_time).total_seconds()
602
+
603
+ if process.returncode == 0:
604
+ try:
605
+ # Try to parse JSON output
606
+ results = json.loads(stdout.decode())
607
+ except json.JSONDecodeError:
608
+ # Fallback to text parsing if JSON fails
609
+ output = stdout.decode().strip()
610
+ results = {"raw_output": output, "query": query}
611
+
612
+ self._update_metrics(True, execution_time)
613
+
614
+ return MCPToolResult(
615
+ success=True,
616
+ data=results,
617
+ execution_time=execution_time,
618
+ metadata={
619
+ "tool": "ticket_search",
620
+ "operation": "search",
621
+ "query": query,
622
+ },
623
+ )
624
+ else:
625
+ error_msg = stderr.decode() if stderr else stdout.decode()
626
+ self._update_metrics(False, execution_time)
627
+
628
+ return MCPToolResult(
629
+ success=False,
630
+ error=f"Failed to search tickets: {error_msg}",
631
+ execution_time=execution_time,
632
+ )
633
+
634
+ except Exception as e:
635
+ execution_time = (datetime.now() - start_time).total_seconds()
636
+ self._update_metrics(False, execution_time)
637
+
638
+ return MCPToolResult(
639
+ success=False,
640
+ error=f"Ticket search failed: {str(e)}",
641
+ execution_time=execution_time,
642
+ )
643
+
644
+
645
+ # Export all ticket tools
646
+ __all__ = [
647
+ "TicketCreateTool",
648
+ "TicketListTool",
649
+ "TicketUpdateTool",
650
+ "TicketViewTool",
651
+ "TicketSearchTool",
652
+ ]